You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
4.7 KiB

package app
import (
"os"
"runtime"
"strings"
"github.com/grvlle/constellation_wallet/backend/models"
"golang.org/x/crypto/bcrypt"
)
// LoginError takes a string and pushes it to the login screen as an errror
func (a *WalletApplication) LoginError(errMsg string) {
if errMsg != "" {
a.RT.Events.Emit("login_error", errMsg, true)
}
}
// Login is called from the FE when a user logs in with a wallet object
// already in the DB
func (a *WalletApplication) Login(keystorePath, keystorePassword, keyPassword, alias string) bool {
alias = strings.ToLower(alias)
a.wallet = models.Wallet{
KeyStorePath: keystorePath,
WalletAlias: alias}
if runtime.GOOS == "windows" && !a.javaInstalled() {
a.LoginError("Unable to detect your Java path. Please make sure that Java has been installed.")
return false
}
if !a.TransactionFinished {
a.log.Warn("Cannot login to another wallet during a pending transaction.")
a.LoginError("Cannot login to another wallet during a pending transaction.")
return false
}
if keystorePath == "" {
a.LoginError("Please provide a path to the KeyStore file.")
return false
}
if !a.passwordsProvided(keystorePassword, keyPassword, alias) {
a.log.Warnln("One or more passwords were not provided.")
return false
}
os.Setenv("CL_STOREPASS", keystorePassword)
os.Setenv("CL_KEYPASS", keyPassword)
if err := a.DB.First(&a.wallet, "wallet_alias = ?", alias).Error; err != nil {
a.log.Errorln("Unable to query database object for existing wallet. Reason: ", err)
return a.ImportWallet(keystorePath, keystorePassword, keyPassword, alias)
}
if !a.WalletKeystoreAccess() {
a.LoginError("Access Denied. Please make sure that you have typed in the correct credentials.")
return false
}
if !a.NewUser {
a.DB.Model(&a.wallet).Update("KeystorePath", keystorePath)
a.log.Infoln("PrivateKey path: ", keystorePath)
}
// Check password strings against salted hashes stored in DB. Also make sure KeyStore has been accessed.
if a.CheckAccess(keystorePassword, a.wallet.KeystorePasswordHash) && a.CheckAccess(keyPassword, a.wallet.KeyPasswordHash) && a.KeyStoreAccess {
a.UserLoggedIn = true
// os.Setenv("CL_STOREPASS", keystorePassword)
// os.Setenv("CL_KEYPASS", keyPassword)
} else {
a.UserLoggedIn = false
a.LoginError("Access Denied. Please make sure that you have typed in the correct credentials.")
}
if a.UserLoggedIn && a.KeyStoreAccess && !a.NewUser {
err := a.initWallet(keystorePath)
if err != nil {
a.UserLoggedIn = false
}
}
a.NewUser = false
return a.UserLoggedIn
}
// CheckTermsOfService is called from the FE to check the termsOfService has been accepted
func (a *WalletApplication) CheckTermsOfService() bool {
return a.wallet.TermsOfService
}
// LogOut will reset the wallet UI and clear the wallet objects
func (a *WalletApplication) LogOut() bool {
if a.TransactionFinished {
a.UserLoggedIn = false
a.wallet = models.Wallet{}
return true
}
a.sendWarning("Cannot log out while transaction is processing. Please try again.")
return false
}
// ImportKey is called from the frontend when browsing the fs for a keyfile
func (a *WalletApplication) ImportKey() string {
var keyfile = a.RT.Dialog.SelectFile()
if keyfile == "" {
a.LoginError("Access Denied. No key path detected.")
return ""
}
if keyfile[len(keyfile)-4:] != ".p12" {
a.LoginError("Access Denied. Not a key file.")
return ""
}
a.log.Info("Path to imported key: " + keyfile)
return keyfile
}
// SelectDirToStoreKey is called from the FE when creating a new keyfile
func (a *WalletApplication) SelectDirToStoreKey() string {
var keyfile = a.RT.Dialog.SelectSaveFile()
if len(keyfile) <= 0 {
a.LoginError("No valid path were provided. Please try again.")
return ""
}
if keyfile[len(keyfile)-4:] != ".p12" {
keyfile = keyfile + ".p12"
return keyfile
}
return keyfile
}
// GenerateSaltedHash converts plain text to a salted hash
func (a *WalletApplication) GenerateSaltedHash(s string) (string, error) {
saltedBytes := []byte(s)
hashedBytes, err := bcrypt.GenerateFromPassword(saltedBytes, bcrypt.DefaultCost)
if err != nil {
return "", err
}
hash := string(hashedBytes[:])
return hash, nil
}
// CheckAccess verifies that the user has entered the correct password
func (a *WalletApplication) CheckAccess(password, passwordHash string) bool {
err := a.Compare(password, passwordHash)
if err != nil {
a.log.Warnln("User tried to login with the wrong credentials!")
return false
}
a.log.Infoln("Password check OK")
return true
}
// Compare compares a string with a salted hash
func (a *WalletApplication) Compare(s, hash string) error {
incoming := []byte(s)
existing := []byte(hash)
return bcrypt.CompareHashAndPassword(existing, incoming)
}