Compare commits
7 Commits
69be01a1db
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67d0d0c8f3 | ||
|
|
67b53cd4c4 | ||
|
|
f162a3300d | ||
|
|
5ee00ccd62 | ||
|
|
8d87af5008 | ||
|
|
7536f12aa7 | ||
|
|
e7b8eb5601 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
go-demo/app-1
|
go-demo/app-1
|
||||||
go-demo-4/data.json
|
go-demo-4/data.json
|
||||||
go-demo-4/.env
|
go-demo-4/.env*
|
||||||
|
go-demo-4/*.vault
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package account
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"password/encrypter"
|
||||||
"password/output"
|
"password/output"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ByteReader interface {
|
type ByteReader interface {
|
||||||
@@ -28,10 +31,11 @@ type Vault struct {
|
|||||||
|
|
||||||
type VaultWithDb struct {
|
type VaultWithDb struct {
|
||||||
Vault
|
Vault
|
||||||
db Db
|
db Db
|
||||||
|
enc encrypter.Encrypter
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVault(db Db) *VaultWithDb {
|
func NewVault(db Db, enc encrypter.Encrypter) *VaultWithDb {
|
||||||
file, err := db.Read()
|
file, err := db.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &VaultWithDb{
|
return &VaultWithDb{
|
||||||
@@ -39,11 +43,14 @@ func NewVault(db Db) *VaultWithDb {
|
|||||||
Accounts: []Account{},
|
Accounts: []Account{},
|
||||||
UpdatedAt: time.Now(),
|
UpdatedAt: time.Now(),
|
||||||
},
|
},
|
||||||
db: db,
|
db: db,
|
||||||
|
enc: enc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
data := enc.Decrypt(file)
|
||||||
var vault Vault
|
var vault Vault
|
||||||
err = json.Unmarshal(file, &vault)
|
err = json.Unmarshal(data, &vault)
|
||||||
|
color.Cyan("Найдено аккаунтов - %d", len(vault.Accounts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
output.PrintError("Не удалось разобрать файл data.json")
|
output.PrintError("Не удалось разобрать файл data.json")
|
||||||
return &VaultWithDb{
|
return &VaultWithDb{
|
||||||
@@ -51,12 +58,14 @@ func NewVault(db Db) *VaultWithDb {
|
|||||||
Accounts: []Account{},
|
Accounts: []Account{},
|
||||||
UpdatedAt: time.Now(),
|
UpdatedAt: time.Now(),
|
||||||
},
|
},
|
||||||
db: db,
|
db: db,
|
||||||
|
enc: enc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &VaultWithDb{
|
return &VaultWithDb{
|
||||||
Vault: vault,
|
Vault: vault,
|
||||||
db: db,
|
db: db,
|
||||||
|
enc: enc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,8 +112,9 @@ func (vault *VaultWithDb) DeleteAccountByUrl(url string) bool {
|
|||||||
func (vault *VaultWithDb) save() {
|
func (vault *VaultWithDb) save() {
|
||||||
vault.UpdatedAt = time.Now()
|
vault.UpdatedAt = time.Now()
|
||||||
data, err := vault.Vault.ToBytes()
|
data, err := vault.Vault.ToBytes()
|
||||||
|
encData := vault.enc.Encrypt(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
output.PrintError("Не удалось преобразовать")
|
output.PrintError("Не удалось преобразовать")
|
||||||
}
|
}
|
||||||
vault.db.Write(data)
|
vault.db.Write(encData)
|
||||||
}
|
}
|
||||||
|
|||||||
58
go-demo-4/encrypter/encrypter.go
Normal file
58
go-demo-4/encrypter/encrypter.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package encrypter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/rand"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Encrypter struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEncrypter() *Encrypter {
|
||||||
|
key := os.Getenv("KEY")
|
||||||
|
if key == "" {
|
||||||
|
panic("Не передан параметр KEY в переменные окружения")
|
||||||
|
}
|
||||||
|
return &Encrypter{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (enc *Encrypter) Encrypt(plainStr []byte) []byte {
|
||||||
|
block, err := aes.NewCipher([]byte(enc.Key))
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
aesGCM, err := cipher.NewGCM(block)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
nonce := make([]byte, aesGCM.NonceSize())
|
||||||
|
_, err = io.ReadFull(rand.Reader, nonce)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
return aesGCM.Seal(nonce, nonce, plainStr, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (enc *Encrypter) Decrypt(encryptedStr []byte) []byte {
|
||||||
|
block, err := aes.NewCipher([]byte(enc.Key))
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
aesGCM, err := cipher.NewGCM(block)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
nonceSize := aesGCM.NonceSize()
|
||||||
|
nonce, cipherText := encryptedStr[:nonceSize], encryptedStr[nonceSize:]
|
||||||
|
plainText, err := aesGCM.Open(nil, nonce, cipherText, nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
return plainText
|
||||||
|
}
|
||||||
@@ -2,7 +2,10 @@ module password
|
|||||||
|
|
||||||
go 1.23.6
|
go 1.23.6
|
||||||
|
|
||||||
require github.com/fatih/color v1.18.0
|
require (
|
||||||
|
github.com/fatih/color v1.18.0
|
||||||
|
github.com/joho/godotenv v1.5.1
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"password/account"
|
"password/account"
|
||||||
|
"password/encrypter"
|
||||||
"password/files"
|
"password/files"
|
||||||
"password/output"
|
"password/output"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var menu = map[string]func(*account.VaultWithDb){
|
var menu = map[string]func(*account.VaultWithDb){
|
||||||
@@ -27,23 +28,26 @@ var menuVariants = []string{
|
|||||||
"Выберите вариант",
|
"Выберите вариант",
|
||||||
}
|
}
|
||||||
|
|
||||||
func menuCounter() func() {
|
// func menuCounter() func() {
|
||||||
i := 0
|
// i := 0
|
||||||
return func() {
|
// return func() {
|
||||||
i++
|
// i++
|
||||||
fmt.Println("Вызов:", i)
|
// fmt.Println("Вызов:", i)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
color.Blue("__Менеджер паролей__")
|
color.Blue("__Менеджер паролей__")
|
||||||
res := os.Getenv("PWD")
|
// Load env file
|
||||||
fmt.Println(res)
|
err := godotenv.Load()
|
||||||
vault := account.NewVault(files.NewJsonDb("data.json"))
|
if err != nil {
|
||||||
counter := menuCounter()
|
output.PrintError("Не удалось найти файл .env")
|
||||||
|
}
|
||||||
|
vault := account.NewVault(files.NewJsonDb("data.vault"), *encrypter.NewEncrypter())
|
||||||
|
// counter := menuCounter()
|
||||||
Menu:
|
Menu:
|
||||||
for {
|
for {
|
||||||
counter()
|
// counter()
|
||||||
variant := PromptData(menuVariants...)
|
variant := PromptData(menuVariants...)
|
||||||
menuFunc := menu[variant]
|
menuFunc := menu[variant]
|
||||||
if menuFunc == nil {
|
if menuFunc == nil {
|
||||||
|
|||||||
34
go-demo-5/geo/geo.go
Normal file
34
go-demo-5/geo/geo.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package geo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GeoData struct {
|
||||||
|
City string `json:"city"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMyLocation(city string) (*GeoData, error) {
|
||||||
|
if city != "" {
|
||||||
|
return &GeoData{
|
||||||
|
City: city,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
resp, err := http.Get("https://ipapi.co/json/")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return nil, errors.New("NOT200")
|
||||||
|
}
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var geo GeoData
|
||||||
|
json.Unmarshal(body, &geo)
|
||||||
|
return &geo, nil
|
||||||
|
}
|
||||||
11
go-demo-5/go.mod
Normal file
11
go-demo-5/go.mod
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module demo/weather
|
||||||
|
|
||||||
|
go 1.24.1
|
||||||
|
|
||||||
|
require github.com/fatih/color v1.18.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
|
)
|
||||||
11
go-demo-5/go.sum
Normal file
11
go-demo-5/go.sum
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
27
go-demo-5/main.go
Normal file
27
go-demo-5/main.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"demo/weather/geo"
|
||||||
|
"demo/weather/weather"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
color.Green("__ПОГОДА__")
|
||||||
|
city := flag.String("city", "", "Город пользователя")
|
||||||
|
format := flag.Int("format", 1, "Формат вывода погоды")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
fmt.Printf("Город: %s\n", *city)
|
||||||
|
geoData, err := geo.GetMyLocation(*city)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
}
|
||||||
|
// fmt.Println(*geoData)
|
||||||
|
weatherData := weather.GetWeather(*geoData, *format)
|
||||||
|
fmt.Println(weatherData)
|
||||||
|
}
|
||||||
31
go-demo-5/weather/weather.go
Normal file
31
go-demo-5/weather/weather.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package weather
|
||||||
|
|
||||||
|
import (
|
||||||
|
"demo/weather/geo"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetWeather(geo geo.GeoData, format int) string {
|
||||||
|
baseUrl, err := url.Parse("https://wttr.in/" + geo.City)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
params := url.Values{}
|
||||||
|
params.Add("format", fmt.Sprint(format))
|
||||||
|
baseUrl.RawQuery = params.Encode()
|
||||||
|
resp, err := http.Get(baseUrl.String())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(body)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user