All checks were successful
CloudSave/pipeline/head This commit looks good
124 lines
2.3 KiB
Go
124 lines
2.3 KiB
Go
package credentials
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"golang.org/x/term"
|
|
)
|
|
|
|
type (
|
|
credential struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
credentialsStore struct {
|
|
Store map[string]credential `json:"store"`
|
|
}
|
|
)
|
|
|
|
var (
|
|
datastorePath string
|
|
)
|
|
|
|
func init() {
|
|
roaming, err := os.UserConfigDir()
|
|
if err != nil {
|
|
panic("failed to get user config path: " + err.Error())
|
|
}
|
|
datastorePath = filepath.Join(roaming, "cloudsave")
|
|
}
|
|
|
|
func Read(server string) (string, string, error) {
|
|
var err error
|
|
store, err := load()
|
|
if err == nil {
|
|
if c, ok := store[server]; ok {
|
|
return c.Username, c.Password, nil
|
|
}
|
|
}
|
|
|
|
fmt.Print("Enter username: ")
|
|
reader := bufio.NewReader(os.Stdin)
|
|
username, _ := reader.ReadString('\n')
|
|
username = strings.TrimSpace(username)
|
|
|
|
fmt.Printf("password for %s: ", username)
|
|
password, err := term.ReadPassword(int(os.Stdin.Fd()))
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
fmt.Println()
|
|
|
|
return username, string(password), nil
|
|
}
|
|
|
|
func Login(username, password, server string) error {
|
|
store, err := load()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
store[server] = credential{
|
|
Username: username,
|
|
Password: password,
|
|
}
|
|
|
|
return save(store)
|
|
}
|
|
|
|
func Logout(server string) error {
|
|
store, err := load()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
delete(store, server)
|
|
|
|
return save(store)
|
|
}
|
|
|
|
func save(store map[string]credential) error {
|
|
c := credentialsStore{
|
|
Store: store,
|
|
}
|
|
|
|
f, err := os.OpenFile(filepath.Join(datastorePath, "credential.json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0740)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to open datastore: %w", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
e := json.NewEncoder(f)
|
|
if err := e.Encode(c); err != nil {
|
|
return fmt.Errorf("failed to encode data: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func load() (map[string]credential, error) {
|
|
f, err := os.OpenFile(filepath.Join(datastorePath, "credential.json"), os.O_RDONLY, 0)
|
|
if err != nil {
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return make(map[string]credential), nil
|
|
}
|
|
return nil, fmt.Errorf("failed to open datastore: %w", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
var c credentialsStore
|
|
d := json.NewDecoder(f)
|
|
if err := d.Decode(&c); err != nil {
|
|
return nil, fmt.Errorf("failed to decode data: %w", err)
|
|
}
|
|
|
|
return c.Store, nil
|
|
}
|