diff --git a/.github/workflows/.goreleaser-for-darwin.yml b/.github/workflows/.goreleaser-for-darwin.yml index 475fd55..d3922b3 100644 --- a/.github/workflows/.goreleaser-for-darwin.yml +++ b/.github/workflows/.goreleaser-for-darwin.yml @@ -18,4 +18,4 @@ builds: - amd64 - arm64 checksum: - disable: true \ No newline at end of file + disable: true diff --git a/.github/workflows/.goreleaser-for-linux.yml b/.github/workflows/.goreleaser-for-linux.yml index c050f50..e2e2a1c 100644 --- a/.github/workflows/.goreleaser-for-linux.yml +++ b/.github/workflows/.goreleaser-for-linux.yml @@ -1,6 +1,7 @@ before: hooks: - go mod tidy + builds: - id: pm main: . diff --git a/.github/workflows/.goreleaser-for-windows.yml b/.github/workflows/.goreleaser-for-windows.yml deleted file mode 100644 index 7928dfe..0000000 --- a/.github/workflows/.goreleaser-for-windows.yml +++ /dev/null @@ -1,21 +0,0 @@ -before: - hooks: - - go mod tidy -builds: - - id: pm - main: . - binary: pm - ldflags: - - -w -s - tags: - - release - env: - - CGO_ENABLED=1 - goos: - - windows - goarch: - - amd64 -checksum: - disable: true -archives: - - format: zip diff --git a/.github/workflows/release_build.yml b/.github/workflows/release_build.yml index 29badc5..83c8b18 100644 --- a/.github/workflows/release_build.yml +++ b/.github/workflows/release_build.yml @@ -20,6 +20,14 @@ jobs: - name: Install cross-compiler for linux/arm64 run: sudo apt-get install -y gcc-aarch64-linux-gnu + - name: Set up git tag + uses: devops-actions/action-get-tag@v1.0.2 + with: + strip_v: false + + - name: Replace __VERSION__ in cmds/root.go + run: sed -i "s/__VERSION__/${{ steps.get_tag.outputs.tag }}/" cmds/root.go + - name: Set up Go uses: actions/setup-go@v4 @@ -28,7 +36,7 @@ jobs: with: distribution: goreleaser version: latest - args: release --config .github/workflows/.goreleaser-for-linux.yml + args: release --skip=validate --config .github/workflows/.goreleaser-for-linux.yml env: GITHUB_TOKEN: ${{ secrets.GO_BUILD_TOKEN}} @@ -48,48 +56,25 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 - - - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v5 - with: - # either 'goreleaser' (default) or 'goreleaser-pro' - distribution: goreleaser - version: latest - args: release --config .github/workflows/.goreleaser-for-darwin.yml - env: - GITHUB_TOKEN: ${{ secrets.GO_BUILD_TOKEN}} - - - name: Upload assets - uses: actions/upload-artifact@v3 - with: - name: myapp - path: dist/* - - release-windows-binary: - runs-on: windows-latest - steps: - - name: Checkout - uses: actions/checkout@v4 with: - fetch-depth: 0 - - - name: Set up MinGW - uses: egor-tensin/setup-mingw@v2 + go-version: 1.23.1 # 指定 Go 版本 + + - name: Set up git tag + uses: devops-actions/action-get-tag@v1.0.2 with: - platform: x64 - version: 12.2.0 - - - name: Set up Go - uses: actions/setup-go@v4 + strip_v: false + + - name: Replace __VERSION__ in cmds/root.go + run: sed -i '' "s/__VERSION__/${{ steps.get_tag.outputs.tag }}/" cmds/root.go - name: Run GoReleaser uses: goreleaser/goreleaser-action@v5 with: + # either 'goreleaser' (default) or 'goreleaser-pro' distribution: goreleaser version: latest - args: release --config .github/workflows/.goreleaser-for-windows.yml + args: release --skip=validate --config .github/workflows/.goreleaser-for-darwin.yml env: - CGO_ENABLE: 1 GITHUB_TOKEN: ${{ secrets.GO_BUILD_TOKEN}} - name: Upload assets @@ -98,31 +83,3 @@ jobs: name: myapp path: dist/* - # goreleaser: - # runs-on: ubuntu-latest - # steps: - # - name: Checkout - # uses: actions/checkout@v4 - # with: - # fetch-depth: 0 - - # - name: Set up Go - # uses: actions/setup-go@v4 - - # - name: Run GoReleaser - # uses: goreleaser/goreleaser-action@v5 - # with: - # # either 'goreleaser' (default) or 'goreleaser-pro' - # distribution: goreleaser - # version: latest - # args: release --clean - # env: - # GITHUB_TOKEN: ${{ secrets.GO_BUILD_TOKEN}} - # # Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution - # # GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} - - # - name: Upload assets - # uses: actions/upload-artifact@v3 - # with: - # name: myapp - # path: myfolder/dist/* diff --git a/Makefile b/Makefile index d9dd8ae..9c88bc2 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,15 @@ ifeq ($(origin GOBIN),undefined) GOBIN := $(GOPATH)/bin endif +# 获取当前的 Git 提交哈希 +GIT_COMMIT := $(shell git rev-parse HEAD) + +# 获取当前的 Git 标签(如果有) +GIT_TAG := $(shell git tag --points-at HEAD 2>/dev/null) + +# 如果没有标签,则使用提交哈希作为版本号 +VERSION := $(if $(GIT_TAG),$(GIT_TAG),$(GIT_COMMIT)) + ## go.build.linux_amd64. .PHONY: build.% build.%: @@ -30,6 +39,7 @@ build.%: $(eval OS := $(word 1,$(subst _, ,$(PLATFORM)))) $(eval ARCH := $(word 2,$(subst _, ,$(PLATFORM)))) @echo "==========> Building binary $(COMMAND) for $(GOOS) $(GOARCH)" + @sed -i 's/__VERSION__/$(VERSION)/' cmds/root.go @GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o bin/$(COMMAND)$(GO_OUT_EXT) main.go ## build: 编译所有服务为二进制可执行文件 diff --git a/cmds/delete.go b/cmds/delete.go index 7e3941a..0b5ccaf 100644 --- a/cmds/delete.go +++ b/cmds/delete.go @@ -70,11 +70,16 @@ func DelCmd() *cobra.Command { os.Exit(1) } - nameList, err := service.store.SearchName(cmd.Context(), toComplete) + passwdList, err := service.store.SearchName(cmd.Context(), toComplete) if err != nil { fmt.Println(err) os.Exit(1) } + + nameList := make([]string, 0) + for _, passed := range passwdList { + nameList = append(nameList, passed.Name) + } return nameList, cobra.ShellCompDirectiveKeepOrder }, } diff --git a/cmds/get.go b/cmds/get.go index 7b04183..65f7ec5 100644 --- a/cmds/get.go +++ b/cmds/get.go @@ -74,11 +74,16 @@ func GetCmd() *cobra.Command { os.Exit(1) } - nameList, err := service.store.SearchName(cmd.Context(), toComplete) + passwdList, err := service.store.SearchName(cmd.Context(), toComplete) if err != nil { fmt.Println(err) os.Exit(1) } + + nameList := make([]string, 0) + for _, passed := range passwdList { + nameList = append(nameList, passed.Name) + } return nameList, cobra.ShellCompDirectiveKeepOrder }, } diff --git a/cmds/init.go b/cmds/init.go index 0fe62d9..6ae0d51 100644 --- a/cmds/init.go +++ b/cmds/init.go @@ -67,6 +67,7 @@ func InitCmd() *cobra.Command { "storeConfig": storeConfigStr, "localPath": filepath.Join(home, ".pm/store"), "userKeyPath": userKeyPath, + "latency": "24h", } tmpl, err := template.New("conf").Parse(confTmpl) if err != nil { diff --git a/cmds/list.go b/cmds/list.go new file mode 100644 index 0000000..a79c692 --- /dev/null +++ b/cmds/list.go @@ -0,0 +1,57 @@ +package cmds + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/yangchnet/pm/config" +) + +func ListCmd() *cobra.Command { + var ( + filterString string + ) + var listCmd = &cobra.Command{ + Use: "list [-f ]", + Short: "list passwd name", + PreRun: func(cmd *cobra.Command, args []string) { + config.InitConfig() + + service, err := NewService(cmd.Context()) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + if err := service.remote.Pull(cmd.Context()); err != nil { + fmt.Println(err) + os.Exit(1) + } + }, + Run: func(cmd *cobra.Command, args []string) { + service, err := NewService(cmd.Context()) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + passwds, err := service.store.SearchName(cmd.Context(), filterString) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + fmt.Printf("%18s| %18s| %18s| %18s|\n", "name", "account", "note", "url") + fmt.Printf("%18s| %18s| %18s| %18s|\n", "-----", "-----", "-----", "-----") + for _, passwd := range passwds { + fmt.Printf("%18s| %18s| %18s| %18s|\n", passwd.Name, passwd.UserName, passwd.Note, passwd.Url) + } + + }, + } + + listCmd.Flags().StringVarP(&filterString, "filter", "f", "", "passwd filter string, default \"\"") + + return listCmd +} diff --git a/cmds/root.go b/cmds/root.go index 5c80840..5c38c95 100644 --- a/cmds/root.go +++ b/cmds/root.go @@ -2,7 +2,10 @@ package cmds import "github.com/spf13/cobra" -var RootCmd = cobra.Command{Use: "pm"} +var RootCmd = cobra.Command{ + Use: "pm", + Version: "__VERSION__", +} func init() { RootCmd.AddCommand(GenerateCmd()) @@ -11,4 +14,6 @@ func init() { RootCmd.AddCommand(PullCmd()) RootCmd.AddCommand(InitCmd()) RootCmd.AddCommand(DelCmd()) + RootCmd.AddCommand(ListCmd()) + RootCmd.AddCommand(UpdateCmd()) } diff --git a/cmds/update.go b/cmds/update.go new file mode 100644 index 0000000..726ce1b --- /dev/null +++ b/cmds/update.go @@ -0,0 +1,96 @@ +package cmds + +import ( + "errors" + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/yangchnet/pm/config" + "github.com/yangchnet/pm/store" + "gorm.io/gorm" +) + +func UpdateCmd() *cobra.Command { + var ( + username string + password string + url string + note string + ) + var updateCmd = &cobra.Command{ + Use: "update [-u username -p password -l url -n note]", + Short: "update passwd", + PreRun: func(cmd *cobra.Command, args []string) { + config.InitConfig() + + service, err := NewService(cmd.Context()) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + if err := service.remote.Pull(cmd.Context()); err != nil { + fmt.Println(err) + os.Exit(1) + } + + if len(args) < 1 { + fmt.Println("必须执行密码名称!") + os.Exit(1) + } + }, + Run: func(cmd *cobra.Command, args []string) { + service, err := NewService(cmd.Context()) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + passwd, err := service.store.Get(cmd.Context(), args[0]) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + fmt.Printf("不存在的密码 [%s]", args[0]) + os.Exit(1) + } + os.Exit(0) + } + + if password != "" { + primaryKey := GetPrimaryKey() + passwd.CryptedPasswd, err = store.Encrypt(primaryKey, []byte(password)) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } + + if note != "" { + passwd.Note = note + } + + if url != "" { + passwd.Url = url + } + + if username != "" { + passwd.UserName = username + } + + fmt.Printf("note: %s; url: %s", note, url) + + err = service.store.Update(cmd.Context(), args[0], passwd) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + }, + } + + updateCmd.Flags().StringVarP(&username, "username", "u", "", "passwd username") + updateCmd.Flags().StringVarP(&url, "url", "l", "", "passwd url") + updateCmd.Flags().StringVarP(¬e, "note", "n", "", "passwd note") + updateCmd.Flags().StringVarP(&password, "password", "p", "", "raw passwd") + + return updateCmd +} diff --git a/cmds/utils.go b/cmds/utils.go index 53d4747..eff9dc8 100644 --- a/cmds/utils.go +++ b/cmds/utils.go @@ -51,8 +51,12 @@ func needPrimaryKeyInput() (string, bool) { lastInputKeyTime := time.Unix(timestamp, 0) - // 如果上一次输出已经超过了24小时,则必须再次输出密码 - if time.Now().Sub(lastInputKeyTime) > time.Hour*24 { + // 如果上一次输出已经超过了给定的延时,则必须再次输出密码 + passwdLatency, err := time.ParseDuration(config.GetString("latency")) + if err != nil { + return "", false + } + if time.Since(lastInputKeyTime) > passwdLatency { _ = os.Remove(userKeyPath) return "", true } diff --git a/go.mod b/go.mod index 7469ce4..3d4592c 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ module github.com/yangchnet/pm -go 1.20 +go 1.23.1 require ( github.com/atotto/clipboard v0.1.4 github.com/go-git/go-git/v5 v5.11.0 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.18.2 - golang.org/x/term v0.15.0 + golang.org/x/term v0.17.0 gorm.io/driver/sqlite v1.5.4 gorm.io/gorm v1.25.5 ) @@ -50,7 +50,7 @@ require ( golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.16.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index d4e37f9..e977277 100644 --- a/go.sum +++ b/go.sum @@ -6,7 +6,9 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5 github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= @@ -18,23 +20,29 @@ github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxG github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -49,9 +57,11 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= @@ -59,6 +69,7 @@ github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= @@ -67,7 +78,9 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= @@ -135,6 +148,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -148,15 +162,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -176,6 +190,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= diff --git a/store/crypt.go b/store/crypt.go index ba681db..2705305 100644 --- a/store/crypt.go +++ b/store/crypt.go @@ -8,6 +8,13 @@ import ( "encoding/base64" "errors" "io" + "os" + + "github.com/yangchnet/pm/config" +) + +var ( + ErrPassword = errors.New("密码错误") ) func createHash(key string) []byte { @@ -34,7 +41,13 @@ func Encrypt(key string, text []byte) ([]byte, error) { return ciphertext, nil } -func Decrypt(key string, text []byte) ([]byte, error) { +func Decrypt(key string, text []byte) (rawPasswd []byte, err error) { + defer func() { + userKeyPath := config.GetString("user_key_path") + if err != nil { + os.Remove(userKeyPath) + } + }() keyHash := createHash(key) block, err := aes.NewCipher(keyHash) @@ -42,7 +55,7 @@ func Decrypt(key string, text []byte) ([]byte, error) { return nil, err } if len(text) < aes.BlockSize { - return nil, errors.New("ciphertext too short") + return nil, ErrPassword } iv := text[:aes.BlockSize] text = text[aes.BlockSize:] @@ -50,7 +63,7 @@ func Decrypt(key string, text []byte) ([]byte, error) { cfb.XORKeyStream(text, text) data, err := base64.StdEncoding.DecodeString(string(text)) if err != nil { - return nil, err + return nil, ErrPassword } return data, nil } diff --git a/store/file-store/file.go b/store/file-store/file.go index 3184a52..e34bac4 100644 --- a/store/file-store/file.go +++ b/store/file-store/file.go @@ -93,26 +93,36 @@ func (s *FileStore) Get(ctx context.Context, name string) (*store.Passwd, error) return &passwd, nil } -// SearchName 根据名称进行搜索并给出名称列表 -func (s *FileStore) SearchName(ctx context.Context, name string) ([]string, error) { +// SearchName 根据名称进行搜索 +func (s *FileStore) SearchName(ctx context.Context, name string) ([]*store.Passwd, error) { files, err := readAllPasswd(s.localPath) if err != nil { return nil, err } - var names []string - for k, _ := range files { + var passwds []*store.Passwd + for k, path := range files { list := strings.Split(k, ".") if len(list) < 1 { continue } if strings.Contains(strings.ToLower(list[0]), strings.ToLower(name)) { - names = append(names, list[0]) + var passwd store.Passwd + content, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + if err := json.Unmarshal(content, &passwd); err != nil { + return nil, err + } + + passwds = append(passwds, &passwd) } } - return names, nil + return passwds, nil } // Delete 删除一个记录 diff --git a/store/interface.go b/store/interface.go index 4cbcb5a..8006c15 100644 --- a/store/interface.go +++ b/store/interface.go @@ -15,7 +15,7 @@ type Store interface { Get(ctx context.Context, name string) (*Passwd, error) // SearchName 根据名称进行搜索并给出名称列表 - SearchName(ctx context.Context, name string) ([]string, error) + SearchName(ctx context.Context, name string) ([]*Passwd, error) // Delete 删除一个记录 Delete(ctx context.Context, name string) error diff --git a/store/sqlite-store/sqlite.go b/store/sqlite-store/sqlite.go index 35cecd7..47d72cb 100644 --- a/store/sqlite-store/sqlite.go +++ b/store/sqlite-store/sqlite.go @@ -3,6 +3,7 @@ package sqlitestore import ( "context" "path/filepath" + "strings" "github.com/yangchnet/pm/config" "github.com/yangchnet/pm/store" @@ -44,7 +45,7 @@ func (s *SqliteStore) Save(ctx context.Context, passwd *store.Passwd) error { // Get 获取密码密文 func (s *SqliteStore) Get(ctx context.Context, name string) (*store.Passwd, error) { var passwd *store.Passwd - if err := s.db.Model(&store.Passwd{}).Where("name = ?", name).First(&passwd).Error; err != nil { + if err := s.db.Model(&store.Passwd{}).Where("LOWER(name) = ?", strings.ToLower(name)).First(&passwd).Error; err != nil { return nil, err } @@ -52,12 +53,12 @@ func (s *SqliteStore) Get(ctx context.Context, name string) (*store.Passwd, erro } // SearchName 根据名称进行搜索并给出名称列表 -func (s *SqliteStore) SearchName(ctx context.Context, name string) ([]string, error) { - var names []string - if err := s.db.Model(&store.Passwd{}).Where("name LIKE ?", "%"+name+"%").Select("name").Scan(&names).Error; err != nil { +func (s *SqliteStore) SearchName(ctx context.Context, name string) ([]*store.Passwd, error) { + var passwds []*store.Passwd + if err := s.db.Model(&store.Passwd{}).Where("LOWER(name) LIKE ?", "%"+strings.ToLower(name)+"%").Find(&passwds).Error; err != nil { return nil, err } - return names, nil + return passwds, nil } // Delete 删除一个记录