Compare commits
4 commits
renovate/g
...
main
Author | SHA1 | Date | |
---|---|---|---|
29e31c5b21 | |||
7ae4c4869e | |||
a16af482de | |||
fd263d8280 |
51 changed files with 396 additions and 204 deletions
|
@ -1,31 +0,0 @@
|
|||
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
|
||||
|
93
.forgejo/workflows/ci.yml
Normal file
93
.forgejo/workflows/ci.yml
Normal file
|
@ -0,0 +1,93 @@
|
|||
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
|
||||
|
||||
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
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
|
12
.golangci.yml
Normal file
12
.golangci.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- wrapcheck
|
||||
- exhaustruct
|
||||
- varnamelen
|
||||
- gochecknoglobals
|
||||
- depguard
|
||||
- gochecknoinits
|
||||
- forbidigo
|
||||
- revive
|
||||
- gosec
|
2
Makefile
2
Makefile
|
@ -8,7 +8,7 @@ GO_BUILD_LD_FLAGS=-ldflags="-s -w -X 'git.dayanhub.com/sagi/envoid/internal/vari
|
|||
build:
|
||||
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=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
|
||||
clean:
|
||||
|
|
14
cmd/env.go
14
cmd/env.go
|
@ -37,12 +37,15 @@ var rmEnvCmd = &cobra.Command{
|
|||
return err
|
||||
}
|
||||
defer ds.Close()
|
||||
|
||||
err = ds.RemoveEnv(*envFlags.rmEnvName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
project.RemoveEnv(*envFlags.rmEnvName)
|
||||
configuration.Save()
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -91,6 +94,7 @@ var addEnvCmd = &cobra.Command{
|
|||
return err
|
||||
}
|
||||
configuration.Save()
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -119,21 +123,27 @@ var lsEnvCmd = &cobra.Command{
|
|||
func init() {
|
||||
// add
|
||||
envFlags.addEnvName = addEnvCmd.Flags().StringP("environment", "e", "", "environment name")
|
||||
|
||||
err := addEnvCmd.MarkFlagRequired("environment")
|
||||
if err != nil {
|
||||
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)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
//rm
|
||||
// rm
|
||||
envFlags.rmEnvName = rmEnvCmd.Flags().StringP("environment", "e", "", "environment name")
|
||||
|
||||
err = rmEnvCmd.MarkFlagRequired("environment")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = rmEnvCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"errors"
|
||||
"git.dayanhub.com/sagi/envoid/internal/datastore"
|
||||
intErrors "git.dayanhub.com/sagi/envoid/internal/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -68,12 +68,14 @@ var getCmd = &cobra.Command{
|
|||
}
|
||||
}
|
||||
fmt.Println(envVar.Value)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
getFlags.envName = getCmd.Flags().StringP("environment", "e", "", "environment name")
|
||||
|
||||
err := getCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -39,8 +39,9 @@ var importCmd = &cobra.Command{
|
|||
}
|
||||
envs = []*types.Environment{e}
|
||||
}
|
||||
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("Needs a file to parse")
|
||||
return errors.NewInvalidCommandError("Missing a file to parse")
|
||||
}
|
||||
|
||||
file, err := os.Open(args[0])
|
||||
|
@ -70,6 +71,7 @@ var importCmd = &cobra.Command{
|
|||
|
||||
func init() {
|
||||
importFlags.envName = importCmd.Flags().StringP("environment", "e", "", "environments name")
|
||||
|
||||
err := importCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -18,6 +18,7 @@ var initCmd = &cobra.Command{
|
|||
_, err := configuration.GetProject(workingDir)
|
||||
if err == nil {
|
||||
fmt.Printf("Project already exists. please remove if you wish to override\n")
|
||||
|
||||
return nil
|
||||
}
|
||||
ds, err := datastore.NewDataStore()
|
||||
|
@ -30,7 +31,7 @@ var initCmd = &cobra.Command{
|
|||
var pass string
|
||||
var envNames []string
|
||||
|
||||
//check if we are importing an existing file
|
||||
// check if we are importing an existing file
|
||||
if ds.DoesFileExists() {
|
||||
fmt.Printf("Project was not found locally. But found %s file in path.\n", variables.DBFileName)
|
||||
fmt.Printf("Importing Project for %s\n", workingDir)
|
||||
|
@ -71,6 +72,7 @@ var initCmd = &cobra.Command{
|
|||
}
|
||||
configuration.Save()
|
||||
fmt.Println("✅ Done")
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
|
|
@ -44,13 +44,13 @@ var printenvCmd = &cobra.Command{
|
|||
}
|
||||
env = e
|
||||
}
|
||||
datastore, err := datastore.NewDataStore()
|
||||
ds, err := datastore.NewDataStore()
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %e", err)
|
||||
}
|
||||
|
||||
defer datastore.Close()
|
||||
vars, err := datastore.GetAll(env.Name)
|
||||
defer ds.Close()
|
||||
vars, err := ds.GetAll(env.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -68,12 +68,14 @@ var printenvCmd = &cobra.Command{
|
|||
fmt.Println("###")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
printenvFlags.envName = printenvCmd.Flags().StringP("environment", "e", "", "environments name")
|
||||
|
||||
err := printenvCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -25,9 +25,11 @@ var lsProjectCmd = &cobra.Command{
|
|||
for _, proj := range configuration.Projects {
|
||||
fmt.Printf("%s\t%s\n", proj.Name, proj.Path)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var rmProjectCmd = &cobra.Command{
|
||||
Use: "rm",
|
||||
Short: "remove a project definition. the `.envoid` file will not be removed",
|
||||
|
@ -36,22 +38,27 @@ var rmProjectCmd = &cobra.Command{
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configuration.RemoveProject(project)
|
||||
configuration.Save()
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
projectFlags.projectPath = rmProjectCmd.Flags().StringP("project-path", "p", "", "project path to remove")
|
||||
|
||||
err := rmProjectCmd.MarkFlagRequired("project-path")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = rmProjectCmd.RegisterFlagCompletionFunc("project-path", validProjectPathComplete)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
projectCmd.AddCommand(lsProjectCmd)
|
||||
projectCmd.AddCommand(rmProjectCmd)
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ var rmCmd = &cobra.Command{
|
|||
|
||||
func init() {
|
||||
rmFlags.envName = rmCmd.Flags().StringP("environment", "e", "", "environments name")
|
||||
|
||||
err := rmCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
31
cmd/root.go
31
cmd/root.go
|
@ -5,22 +5,26 @@ import (
|
|||
"os"
|
||||
|
||||
"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/variables"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/cobra/doc"
|
||||
)
|
||||
|
||||
var configuration *config.Config = nil
|
||||
var workingDir string
|
||||
var project *types.Project = nil
|
||||
var (
|
||||
configuration *config.Config = nil
|
||||
workingDir string
|
||||
project *types.Project = nil
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "envoid [command]",
|
||||
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.
|
||||
|
||||
envoid works offline and creates different encrypted environments for each project. It's mainly used to store,encrypt (with a passphrase) and share
|
||||
envoid works offline and creates different encrypted environments for each project.
|
||||
It's mainly used to store,encrypt (with a passphrase) and share
|
||||
.env variables`,
|
||||
Version: fmt.Sprintf("%s commit %s", variables.Version, variables.Commit),
|
||||
}
|
||||
|
@ -33,6 +37,7 @@ var docCmd = &cobra.Command{
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -46,8 +51,9 @@ func Execute() {
|
|||
|
||||
func checkAmbiguousEnv(envName string) error {
|
||||
if len(envName) == 0 && len(project.Environments) > 1 {
|
||||
return fmt.Errorf("You have more than 1 environment. please provide environment name")
|
||||
return errors.NewNoEnvProvidedError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -56,25 +62,34 @@ func initProject() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
project = p
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validEnvironmentNamesComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
func validEnvironmentNamesComplete(cmd *cobra.Command, args []string,
|
||||
toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
envs := []string{}
|
||||
|
||||
if err := initProject(); err == nil {
|
||||
for _, e := range project.Environments {
|
||||
envs = append(envs, e.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return envs, cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
|
||||
func validProjectPathComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
func validProjectPathComplete(cmd *cobra.Command, args []string,
|
||||
toComplete string,
|
||||
) ([]string, cobra.ShellCompDirective) {
|
||||
paths := []string{}
|
||||
for _, p := range configuration.Projects {
|
||||
paths = append(paths, fmt.Sprintf("%s\t%s", p.Path, p.Name))
|
||||
}
|
||||
|
||||
return paths, cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
|
||||
|
@ -90,10 +105,12 @@ func init() {
|
|||
rootCmd.AddCommand(projectCmd)
|
||||
|
||||
configuration = config.GetConfig()
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Printf("[error] %s. please run 'ssecret init'\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
workingDir = pwd
|
||||
}
|
||||
|
|
19
cmd/set.go
19
cmd/set.go
|
@ -21,13 +21,15 @@ var setCmd = &cobra.Command{
|
|||
Use: "set [flags] <key> <value>",
|
||||
Short: "sets a variable in environment(s)",
|
||||
Long: "",
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 2 {
|
||||
Args: func(_ *cobra.Command, args []string) error {
|
||||
expectedArgs := 2
|
||||
if len(args) != expectedArgs {
|
||||
return errors.NewInvalidCommandError("expected 2 args. <key> <value>")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
err := initProject()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -57,6 +59,7 @@ var setCmd = &cobra.Command{
|
|||
if err != nil {
|
||||
fmt.Printf("Error: %s\n", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -65,13 +68,15 @@ var setEncryptCmd = &cobra.Command{
|
|||
Use: "encrypt <key>",
|
||||
Short: "encrypts an existing variable in environment(s)",
|
||||
Long: "",
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 {
|
||||
Args: func(_ *cobra.Command, args []string) error {
|
||||
expectedArgs := 1
|
||||
if len(args) != expectedArgs {
|
||||
return errors.NewInvalidCommandError("expected 1 args. <key>")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
err := initProject()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -117,9 +122,11 @@ var setEncryptCmd = &cobra.Command{
|
|||
func init() {
|
||||
setFlags.envName = setCmd.PersistentFlags().StringP("environment", "e", "", "environments name")
|
||||
setFlags.encrypt = setCmd.Flags().BoolP("secret", "s", false, "value is a secret. encrypt this value")
|
||||
|
||||
err := setCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
setCmd.AddCommand(setEncryptCmd)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ 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. It's mainly used to store,encrypt (with a passphrase) and share
|
||||
envoid works offline and creates different encrypted environments for each project.
|
||||
It's mainly used to store,encrypt (with a passphrase) and share
|
||||
.env variables
|
||||
|
||||
### Options
|
||||
|
@ -27,4 +28,4 @@ envoid works offline and creates different encrypted environments for each proje
|
|||
* [envoid rm](envoid_rm.md) - removes a variable from environment(s)
|
||||
* [envoid set](envoid_set.md) - sets a variable in environment(s)
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -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 zsh](envoid_completion_zsh.md) - Generate the autocompletion script for zsh
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -41,4 +41,4 @@ envoid completion bash
|
|||
|
||||
* [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -32,4 +32,4 @@ envoid completion fish [flags]
|
|||
|
||||
* [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -29,4 +29,4 @@ envoid completion powershell [flags]
|
|||
|
||||
* [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -43,4 +43,4 @@ envoid completion zsh [flags]
|
|||
|
||||
* [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -15,4 +15,4 @@ manage environments
|
|||
* [envoid env ls](envoid_env_ls.md) - list all environments in this project
|
||||
* [envoid env rm](envoid_env_rm.md) - removes an environment
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -18,4 +18,4 @@ envoid env add [flags]
|
|||
|
||||
* [envoid env](envoid_env.md) - manage environments
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -16,4 +16,4 @@ envoid env ls [flags]
|
|||
|
||||
* [envoid env](envoid_env.md) - manage environments
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -17,4 +17,4 @@ envoid env rm [flags]
|
|||
|
||||
* [envoid env](envoid_env.md) - manage environments
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -17,4 +17,4 @@ envoid get <key> [flags]
|
|||
|
||||
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -21,4 +21,4 @@ envoid import <file> [flags]
|
|||
|
||||
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -16,4 +16,4 @@ envoid init [flags]
|
|||
|
||||
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -17,4 +17,4 @@ envoid printenv [flags]
|
|||
|
||||
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -14,4 +14,4 @@ manage project
|
|||
* [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
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -16,4 +16,4 @@ envoid project ls [flags]
|
|||
|
||||
* [envoid project](envoid_project.md) - manage project
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -17,4 +17,4 @@ envoid project rm [flags]
|
|||
|
||||
* [envoid project](envoid_project.md) - manage project
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -17,4 +17,4 @@ envoid rm <key> [flags]
|
|||
|
||||
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -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 set encrypt](envoid_set_encrypt.md) - encrypts an existing variable in environment(s)
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
|
@ -22,4 +22,4 @@ envoid set encrypt <key> [flags]
|
|||
|
||||
* [envoid set](envoid_set.md) - sets a variable in environment(s)
|
||||
|
||||
###### Auto generated by spf13/cobra on 12-Dec-2024
|
||||
###### Auto generated by spf13/cobra on 16-Dec-2024
|
||||
|
|
8
go.mod
8
go.mod
|
@ -7,9 +7,9 @@ require (
|
|||
github.com/glebarez/go-sqlite v1.22.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/spf13/cobra v1.8.1
|
||||
golang.org/x/crypto v0.29.0
|
||||
golang.org/x/sync v0.9.0
|
||||
golang.org/x/term v0.26.0
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/sync v0.10.0
|
||||
golang.org/x/term v0.27.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -21,7 +21,7 @@ require (
|
|||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.37.6 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
|
|
16
go.sum
16
go.sum
|
@ -24,15 +24,15 @@ 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/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
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/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
||||
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/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
|
|
@ -6,5 +6,6 @@ func StrToSnakeCase(s string) string {
|
|||
snake := strings.ToLower(s)
|
||||
snake = strings.ReplaceAll(snake, " ", "_")
|
||||
snake = strings.ReplaceAll(snake, "\t", "_")
|
||||
|
||||
return snake
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
|
@ -14,33 +15,40 @@ import (
|
|||
|
||||
type Config struct {
|
||||
PWD string `json:"-"`
|
||||
Projects []*types.Project `json:"projects" default:"[]"`
|
||||
Projects []*types.Project `default:"[]" json:"projects"`
|
||||
}
|
||||
|
||||
var configPath string
|
||||
|
||||
var configStruct *Config
|
||||
|
||||
func (c *Config) GetProject(projectPath string) (*types.Project, error) {
|
||||
var p *types.Project
|
||||
|
||||
for _, project := range configStruct.Projects {
|
||||
if project.Path == projectPath {
|
||||
p = project
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if p == nil {
|
||||
return nil, errors.NewProjectNotFoundError(projectPath)
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (c *Config) RemoveProject(project *types.Project) {
|
||||
projects := []*types.Project{}
|
||||
|
||||
for _, p := range c.Projects {
|
||||
if p.Name != project.Name && p.Path != project.Path {
|
||||
projects = append(projects, p)
|
||||
}
|
||||
}
|
||||
|
||||
c.Projects = projects
|
||||
}
|
||||
|
||||
|
@ -54,7 +62,9 @@ func (c *Config) NewProject(name string, path string, password string) (*types.P
|
|||
Environments: []*types.Environment{},
|
||||
}
|
||||
configStruct.Projects = append(configStruct.Projects, p)
|
||||
|
||||
SaveConfig()
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
|
@ -79,46 +89,53 @@ func init() {
|
|||
fmt.Printf("[ERROR] Failed to fetch user config directory. %e\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(configDir); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(configDir, 0700)
|
||||
var folderPermissions fs.FileMode = 0o700
|
||||
|
||||
err := os.MkdirAll(configDir, folderPermissions)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var configFile *os.File
|
||||
|
||||
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
||||
configFile, err = os.Create(configPath)
|
||||
defer func() {
|
||||
err = configFile.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] Failed to create config file @ %s. %e\n", configPath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
defer configFile.Close()
|
||||
}
|
||||
|
||||
configStruct, err = loadConfig()
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] Failed to load config file @ %s. %e\n", configPath, err)
|
||||
os.Exit(1)
|
||||
configFile.Close()
|
||||
panic("")
|
||||
}
|
||||
}
|
||||
|
||||
func loadConfig() (*Config, error) {
|
||||
c := &Config{}
|
||||
|
||||
err := defaults.Set(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
file, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(file) == 0 {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(file, c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -127,7 +144,9 @@ func loadConfig() (*Config, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.PWD = pwd
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
@ -137,7 +156,10 @@ func SaveConfig() {
|
|||
fmt.Printf("[ERROR] Failed to convert config to json. %e\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = os.WriteFile(configPath, yml, 0600)
|
||||
|
||||
var filePermissions fs.FileMode = 0o600
|
||||
|
||||
err = os.WriteFile(configPath, yml, filePermissions)
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] Failed to save config file @ %s. %e\n", configPath, err)
|
||||
os.Exit(1)
|
||||
|
|
|
@ -18,84 +18,98 @@ import (
|
|||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type datastore struct {
|
||||
type Datastore struct {
|
||||
db *db
|
||||
}
|
||||
|
||||
func NewDataStore() (*datastore, error) {
|
||||
func NewDataStore() (*Datastore, error) {
|
||||
db, err := newDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &datastore{
|
||||
return &Datastore{
|
||||
db: db,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *datastore) CreateEnv(name string) error {
|
||||
table_name := envNameToTableName(name)
|
||||
return d.db.createTableIfNotExists(table_name)
|
||||
func (d *Datastore) CreateEnv(name string) error {
|
||||
tableName := envNameToTableName(name)
|
||||
|
||||
return d.db.createTableIfNotExists(tableName)
|
||||
}
|
||||
|
||||
func (d *datastore) DoesFileExists() bool {
|
||||
func (d *Datastore) DoesFileExists() bool {
|
||||
pwd := config.GetConfig().PWD
|
||||
filePath := fmt.Sprintf("%s/%s", pwd, variables.DBFileName)
|
||||
|
||||
if _, err := os.Stat(filePath); errors.Is(err, os.ErrNotExist) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *datastore) ListEnvironments() ([]string, error) {
|
||||
func (d *Datastore) ListEnvironments() ([]string, error) {
|
||||
return d.db.listTables()
|
||||
}
|
||||
|
||||
func (d *datastore) CreateEnvOffExsisting(new_env string, base_env string) error {
|
||||
table_name_new := envNameToTableName(new_env)
|
||||
table_name_base := envNameToTableName(base_env)
|
||||
err := d.CreateEnv(new_env)
|
||||
func (d *Datastore) CreateEnvOffExsisting(newEnv string, baseEnv string) error {
|
||||
tableNameName := envNameToTableName(newEnv)
|
||||
tableNameBase := envNameToTableName(baseEnv)
|
||||
|
||||
err := d.CreateEnv(newEnv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = d.db.copyContentFromTo(table_name_base, table_name_new)
|
||||
|
||||
err = d.db.copyContentFromTo(tableNameBase, tableNameName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *datastore) Close() error {
|
||||
func (d *Datastore) Close() error {
|
||||
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 {
|
||||
encrypted = common.BoolP(false)
|
||||
}
|
||||
|
||||
if *encrypted {
|
||||
v, err := enc(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value = *v
|
||||
}
|
||||
|
||||
for _, env := range envs {
|
||||
table_name := envNameToTableName(env.Name)
|
||||
if err := d.db.setVar(table_name, key, value, *encrypted); err != nil {
|
||||
tableName := envNameToTableName(env.Name)
|
||||
|
||||
if err := d.db.setVar(tableName, key, value, *encrypted); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *datastore) GetAll(envName string) ([]*types.EnvVar, error) {
|
||||
table_name := envNameToTableName(envName)
|
||||
vars, err := d.db.getAll(table_name)
|
||||
func (d *Datastore) GetAll(envName string) ([]*types.EnvVar, error) {
|
||||
tableName := envNameToTableName(envName)
|
||||
|
||||
vars, err := d.db.getAll(tableName)
|
||||
if err != nil {
|
||||
return vars, err
|
||||
}
|
||||
|
||||
g := new(errgroup.Group)
|
||||
|
||||
for _, v := range vars {
|
||||
g.Go(func() error {
|
||||
if v.Encrypted {
|
||||
|
@ -103,42 +117,50 @@ func (d *datastore) GetAll(envName string) ([]*types.EnvVar, error) {
|
|||
return &intErrors.InvalidPasswordError{}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
return vars, err
|
||||
}
|
||||
|
||||
sort.SliceStable(vars, func(i, j int) bool {
|
||||
return vars[i].Key < vars[j].Key
|
||||
})
|
||||
|
||||
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 {
|
||||
table_name := envNameToTableName(env.Name)
|
||||
d.db.rmVar(table_name, key)
|
||||
tableName := envNameToTableName(env.Name)
|
||||
d.db.rmVar(tableName, key)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *datastore) GetVar(envName string, key string) (*types.EnvVar, error) {
|
||||
table_name := envNameToTableName(envName)
|
||||
v, err := d.db.getVar(table_name, key)
|
||||
func (d *Datastore) GetVar(envName string, key string) (*types.EnvVar, error) {
|
||||
tableName := envNameToTableName(envName)
|
||||
|
||||
v, err := d.db.getVar(tableName, key)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
|
||||
if v.Encrypted {
|
||||
if v.Value, err = dec(v.Value); err != nil {
|
||||
return v, &intErrors.InvalidPasswordError{}
|
||||
}
|
||||
}
|
||||
|
||||
return v, err
|
||||
}
|
||||
|
||||
func (d *datastore) RemoveEnv(envName string) error {
|
||||
table_name := envNameToTableName(envName)
|
||||
return d.db.deleteTable(table_name)
|
||||
func (d *Datastore) RemoveEnv(envName string) error {
|
||||
tableName := envNameToTableName(envName)
|
||||
|
||||
return d.db.deleteTable(tableName)
|
||||
}
|
||||
|
||||
func enc(s string) (*string, error) {
|
||||
|
@ -146,6 +168,7 @@ func enc(s string) (*string, error) {
|
|||
proj, _ := conf.GetProject(conf.PWD)
|
||||
key, salt, err := deriveKey([]byte(proj.Password), nil)
|
||||
data := []byte(s)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -179,6 +202,7 @@ func dec(s string) (string, error) {
|
|||
|
||||
conf := config.GetConfig()
|
||||
proj, _ := conf.GetProject(conf.PWD)
|
||||
|
||||
key, _, err := deriveKey([]byte(proj.Password), salt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -207,14 +231,19 @@ func dec(s string) (string, error) {
|
|||
}
|
||||
|
||||
func deriveKey(password, salt []byte) ([]byte, []byte, error) {
|
||||
saltSize := 32
|
||||
if salt == nil {
|
||||
salt = make([]byte, 32)
|
||||
salt = make([]byte, saltSize)
|
||||
if _, err := rand.Read(salt); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
key, err := scrypt.Key(password, salt, 1048576, 8, 1, 32)
|
||||
N := 1048576
|
||||
r := 8
|
||||
p := 1
|
||||
|
||||
key, err := scrypt.Key(password, salt, N, r, p, saltSize)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"git.dayanhub.com/sagi/envoid/internal/common"
|
||||
"git.dayanhub.com/sagi/envoid/internal/errors"
|
||||
|
@ -20,6 +19,7 @@ func newDB() (*db, error) {
|
|||
con, err := sql.Open("sqlite", variables.DBFileName)
|
||||
if err != nil {
|
||||
fmt.Printf("%v\n", err)
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -32,72 +32,91 @@ func (d *db) close() error {
|
|||
return d.con.Close()
|
||||
}
|
||||
|
||||
func (d *db) createTableIfNotExists(table_name string) error {
|
||||
_, 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))
|
||||
func (d *db) createTableIfNotExists(tableName string) error {
|
||||
q := "CREATE TABLE IF NOT EXISTS " + tableName +
|
||||
" (key TEXT PRIMARY KEY NOT NULL,value BLOB NOT NULL,encrypted BOOL NOT NULL);"
|
||||
|
||||
_, err := d.con.Exec(q)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *db) listTables() ([]string, error) {
|
||||
tables := []string{}
|
||||
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))
|
||||
if err != nil {
|
||||
|
||||
rows, err := d.con.Query(q, variables.DBTablePrefix+"_%%")
|
||||
if err != nil || rows.Err() != nil {
|
||||
return tables, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var table string
|
||||
|
||||
if err := rows.Scan(&table); err != nil {
|
||||
return tables, err
|
||||
}
|
||||
|
||||
tables = append(tables, tableNameToEnvName(table))
|
||||
}
|
||||
|
||||
return tables, nil
|
||||
}
|
||||
|
||||
func (d *db) copyContentFromTo(table_name_target string, table_name_dest string) error {
|
||||
_, err := d.con.Exec(fmt.Sprintf("INSERT INTO %s (key, value, encrypted) SELECT * FROM %s", table_name_dest, table_name_target))
|
||||
func (d *db) copyContentFromTo(tableNameTarget string, tableNameDest string) error {
|
||||
_, err := d.con.Exec(
|
||||
fmt.Sprintf("INSERT INTO %s (key, value, encrypted) SELECT * FROM %s",
|
||||
tableNameDest, tableNameTarget),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *db) deleteTable(table_name string) error {
|
||||
_, err := d.con.Exec(fmt.Sprintf("DROP TABLE IF EXISTS %s", table_name))
|
||||
func (d *db) deleteTable(tableName string) error {
|
||||
_, err := d.con.Exec("DROP TABLE IF EXISTS " + tableName)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *db) getVar(table_name string, key string) (*types.EnvVar, error) {
|
||||
q := fmt.Sprintf("SELECT * FROM %s WHERE key=?", table_name)
|
||||
func (d *db) getVar(tableName string, key string) (*types.EnvVar, error) {
|
||||
q := "SELECT * FROM " + tableName + " WHERE key=?"
|
||||
row := d.con.QueryRow(q, key)
|
||||
envVar := &types.EnvVar{}
|
||||
|
||||
err := row.Scan(&envVar.Key, &envVar.Value, &envVar.Encrypted)
|
||||
if err != nil {
|
||||
return envVar, errors.NewNoKeyFoundError(key)
|
||||
}
|
||||
|
||||
return envVar, nil
|
||||
|
||||
}
|
||||
|
||||
func (d *db) getAll(table_name string) ([]*types.EnvVar, error) {
|
||||
func (d *db) getAll(tableName string) ([]*types.EnvVar, error) {
|
||||
entries := []*types.EnvVar{}
|
||||
rows, err := d.con.Query(fmt.Sprintf("SELECT * FROM %s", table_name))
|
||||
if err != nil {
|
||||
|
||||
rows, err := d.con.Query("SELECT * FROM " + tableName)
|
||||
if err != nil || rows.Err() != nil {
|
||||
return entries, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
key := ""
|
||||
value := ""
|
||||
enc := common.BoolP(false)
|
||||
|
||||
err := rows.Scan(&key, &value, enc)
|
||||
if err != nil {
|
||||
return entries, err
|
||||
}
|
||||
|
||||
e := &types.EnvVar{
|
||||
Key: key,
|
||||
Value: value,
|
||||
|
@ -105,27 +124,33 @@ func (d *db) getAll(table_name string) ([]*types.EnvVar, error) {
|
|||
}
|
||||
entries = append(entries, e)
|
||||
}
|
||||
return entries, nil
|
||||
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
func (d *db) setVar(table_name string, key string, value string, encrypted bool) error {
|
||||
q := fmt.Sprintf("INSERT INTO %s (key, value, encrypted) values ( ? , ? , ? ) ON CONFLICT (key) DO UPDATE SET value = ?, encrypted = ?", table_name)
|
||||
func (d *db) setVar(tableName string, key string, value string, encrypted bool) error {
|
||||
q := "INSERT INTO " +
|
||||
tableName +
|
||||
" (key,value,encrypted) values (?,?,?) ON CONFLICT (key) DO UPDATE SET value=?, encrypted=?"
|
||||
|
||||
_, err := d.con.Exec(q, key, value, encrypted, value, encrypted)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
|
||||
return errors.NewSecretExsistsError(key)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *db) rmVar(table_name string, key string) {
|
||||
q := fmt.Sprintf("DELETE FROM %s WHERE key = ?", table_name)
|
||||
func (d *db) rmVar(tableName string, key string) {
|
||||
q := "DELETE FROM " + tableName + " WHERE key = ?"
|
||||
_, _ = d.con.Exec(q, key)
|
||||
}
|
||||
|
||||
func envNameToTableName(envName string) string {
|
||||
envSanke := common.StrToSnakeCase(envName)
|
||||
|
||||
return fmt.Sprintf("%s_%s", variables.DBTablePrefix, envSanke)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type EnvironmentExistsError struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (e *EnvironmentExistsError) Error() string {
|
||||
return fmt.Sprintf("environment %s already exists", e.name)
|
||||
return "environment " + e.name + " already exists"
|
||||
}
|
||||
|
||||
func NewEnvironmentExistsError(name string) *EnvironmentExistsError {
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type InvalidCommandError struct {
|
||||
msg string
|
||||
}
|
||||
|
||||
func (e *InvalidCommandError) Error() string {
|
||||
return fmt.Sprintf("invalid command. %v", e.msg)
|
||||
return "invalid command. " + e.msg
|
||||
}
|
||||
|
||||
func NewInvalidCommandError(msg string) *InvalidCommandError {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package errors
|
||||
|
||||
type InvalidPasswordError struct {
|
||||
}
|
||||
type InvalidPasswordError struct{}
|
||||
|
||||
func (e *InvalidPasswordError) Error() string {
|
||||
return "invalid password. is your environment set correctly?"
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type NoKeyFoundError struct {
|
||||
key string
|
||||
}
|
||||
|
||||
func (e *NoKeyFoundError) Error() string {
|
||||
return fmt.Sprintf("key %s not found", e.key)
|
||||
return "key " + e.key + " not found"
|
||||
}
|
||||
|
||||
func NewNoKeyFoundError(key string) *NoKeyFoundError {
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type NoConfigFoundError struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func (e *NoConfigFoundError) Error() string {
|
||||
return fmt.Sprintf("no config file found in %s", e.path)
|
||||
return "no config file found in " + e.path
|
||||
}
|
||||
|
||||
func NewNoConfigFoundError(path string) *NoConfigFoundError {
|
||||
|
|
11
internal/errors/no_env_provided.go
Normal file
11
internal/errors/no_env_provided.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
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{}
|
||||
}
|
|
@ -1,13 +1,11 @@
|
|||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type ProjectEmptyError struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (e *ProjectEmptyError) Error() string {
|
||||
return fmt.Sprintf("Project %s does not have any environments.", e.name)
|
||||
return "Project " + e.name + " does not have any environments."
|
||||
}
|
||||
|
||||
func NewProjectEmptyError(name string) *ProjectEmptyError {
|
||||
|
|
|
@ -9,15 +9,20 @@ import (
|
|||
)
|
||||
|
||||
func PasswordPrompt(label string) string {
|
||||
var s string
|
||||
var str string
|
||||
|
||||
for {
|
||||
fmt.Fprint(os.Stderr, label+" ")
|
||||
b, _ := term.ReadPassword(int(syscall.Stdin))
|
||||
s = string(b)
|
||||
if s != "" {
|
||||
|
||||
b, _ := term.ReadPassword(syscall.Stdin)
|
||||
|
||||
str = string(b)
|
||||
if str != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
return s
|
||||
|
||||
return str
|
||||
}
|
||||
|
|
|
@ -8,14 +8,18 @@ import (
|
|||
)
|
||||
|
||||
func StringPrompt(label string) string {
|
||||
var s string
|
||||
var str string
|
||||
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
|
||||
for {
|
||||
fmt.Fprint(os.Stderr, label+" ")
|
||||
s, _ = r.ReadString('\n')
|
||||
if s != "" {
|
||||
|
||||
str, _ = r.ReadString('\n')
|
||||
if str != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
return strings.TrimSpace(s)
|
||||
|
||||
return strings.TrimSpace(str)
|
||||
}
|
||||
|
|
|
@ -12,11 +12,12 @@ type Project struct {
|
|||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
Environments []*Environment `json:"envorinments" default:"[]"`
|
||||
Environments []*Environment `default:"[]" json:"envorinments"`
|
||||
}
|
||||
|
||||
func (p *Project) GetEnv(name string) (*Environment, error) {
|
||||
var e *Environment
|
||||
|
||||
for _, env := range p.Environments {
|
||||
if env.Name == name {
|
||||
passByte, err := base64.RawStdEncoding.DecodeString(p.Password)
|
||||
|
@ -24,32 +25,39 @@ func (p *Project) GetEnv(name string) (*Environment, error) {
|
|||
fmt.Printf("[ERROR] Failed to decode project password @ %s. %e\n", p.Path, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
e = &Environment{
|
||||
Name: env.Name,
|
||||
Password: string(passByte),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if e == nil {
|
||||
return nil, errors.NewEnvironmentNotFoundError(p.Path, name)
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func (p *Project) NewEnv(name string) error {
|
||||
e := &Environment{
|
||||
Name: name,
|
||||
}
|
||||
p.Environments = append(p.Environments, e)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Project) RemoveEnv(name string) {
|
||||
environments := []*Environment{}
|
||||
|
||||
for _, env := range p.Environments {
|
||||
if env.Name != name {
|
||||
environments = append(environments, env)
|
||||
}
|
||||
}
|
||||
|
||||
p.Environments = environments
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package variables
|
||||
|
||||
var (
|
||||
Commit string = "HEAD"
|
||||
Version string = "development"
|
||||
Commit = "HEAD"
|
||||
Version = "development"
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue