Compare commits

..

9 Commits

Author SHA1 Message Date
Archie Fox
67d0d0c8f3 delete hidden directory 2025-05-15 10:52:07 +03:00
Archie Fox
67b53cd4c4 Fix string format 2025-03-26 22:29:46 +03:00
Archie Fox
f162a3300d Weather app: http requests 2025-03-24 21:10:02 +03:00
Archer Fox
5ee00ccd62 New project: Weather app 2025-03-20 23:45:11 +03:00
Archer Fox
8d87af5008 Add encrypt and decrypt data in file 2025-03-20 23:12:55 +03:00
Archer Fox
7536f12aa7 Add encrypt and decrypt function 2025-03-19 23:37:15 +03:00
Archer Fox
e7b8eb5601 Add environment variables and encryptor package 2025-03-18 22:04:43 +03:00
Archer Fox
69be01a1db Merge branch 'main' of https://dev-fox.ru/fox/purpleschool 2025-03-18 21:28:27 +03:00
Archer Fox
dd4aca086d Добавлено: несколько аргументов функции и замыкание 2025-03-18 21:27:50 +03:00
11 changed files with 213 additions and 17 deletions

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
go-demo/app-1
go-demo-4/data.json
go-demo-4/.env*
go-demo-4/*.vault

View File

@@ -2,9 +2,12 @@ package account
import (
"encoding/json"
"password/encrypter"
"password/output"
"strings"
"time"
"github.com/fatih/color"
)
type ByteReader interface {
@@ -28,10 +31,11 @@ type Vault struct {
type VaultWithDb struct {
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()
if err != nil {
return &VaultWithDb{
@@ -39,11 +43,14 @@ func NewVault(db Db) *VaultWithDb {
Accounts: []Account{},
UpdatedAt: time.Now(),
},
db: db,
db: db,
enc: enc,
}
}
data := enc.Decrypt(file)
var vault Vault
err = json.Unmarshal(file, &vault)
err = json.Unmarshal(data, &vault)
color.Cyan("Найдено аккаунтов - %d", len(vault.Accounts))
if err != nil {
output.PrintError("Не удалось разобрать файл data.json")
return &VaultWithDb{
@@ -51,12 +58,14 @@ func NewVault(db Db) *VaultWithDb {
Accounts: []Account{},
UpdatedAt: time.Now(),
},
db: db,
db: db,
enc: enc,
}
}
return &VaultWithDb{
Vault: vault,
db: db,
enc: enc,
}
}
@@ -103,8 +112,9 @@ func (vault *VaultWithDb) DeleteAccountByUrl(url string) bool {
func (vault *VaultWithDb) save() {
vault.UpdatedAt = time.Now()
data, err := vault.Vault.ToBytes()
encData := vault.enc.Encrypt(data)
if err != nil {
output.PrintError("Не удалось преобразовать")
}
vault.db.Write(data)
vault.db.Write(encData)
}

View 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
}

View File

@@ -2,7 +2,10 @@ module password
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 (
github.com/mattn/go-colorable v0.1.13 // indirect

View File

@@ -1,5 +1,7 @@
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/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/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=

View File

@@ -3,11 +3,13 @@ package main
import (
"fmt"
"password/account"
"password/encrypter"
"password/files"
"password/output"
"strings"
"github.com/fatih/color"
"github.com/joho/godotenv"
)
var menu = map[string]func(*account.VaultWithDb){
@@ -26,21 +28,26 @@ var menuVariants = []string{
"Выберите вариант",
}
func menuCounter() func() {
i := 0
return func() {
i++
fmt.Println("Вызов:", i)
}
}
// func menuCounter() func() {
// i := 0
// return func() {
// i++
// fmt.Println("Вызов:", i)
// }
// }
func main() {
color.Blue("__Менеджер паролей__")
vault := account.NewVault(files.NewJsonDb("data.json"))
counter := menuCounter()
// Load env file
err := godotenv.Load()
if err != nil {
output.PrintError("Не удалось найти файл .env")
}
vault := account.NewVault(files.NewJsonDb("data.vault"), *encrypter.NewEncrypter())
// counter := menuCounter()
Menu:
for {
counter()
// counter()
variant := PromptData(menuVariants...)
menuFunc := menu[variant]
if menuFunc == nil {

34
go-demo-5/geo/geo.go Normal file
View 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
View 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
View 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
View 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)
}

View 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)
}