Auth flow

This commit is contained in:
Zach Fox 2017-08-31 15:16:29 -07:00
parent ce32d2d420
commit eab2947d40
10 changed files with 154 additions and 166 deletions

View file

@ -29,7 +29,6 @@ Rectangle {
property bool purchasesReceived: false;
property bool balanceReceived: false;
property bool securityImageResultReceived: false;
property bool keyFilePathIfExistsResultReceived: false;
property string itemId: "";
property string itemHref: "";
property double balanceAfterPurchase: 0;
@ -46,38 +45,15 @@ Rectangle {
root.activeView = "needsLogIn";
} else if (isLoggedIn) {
root.activeView = "initialize";
commerce.getPassphraseSetupStatus();
}
}
onPassphraseSetupStatusResult: {
if (!passphraseIsSetup && root.activeView !== "notSetUp") {
root.activeView = "notSetUp";
} else if (passphraseIsSetup && root.activeView === "initialize") {
commerce.getWalletAuthenticatedStatus();
commerce.getKeyFilePathIfExists();
}
}
onWalletAuthenticatedStatusResult: {
if (!isAuthenticated && !passphraseModal.visible) {
passphraseModal.visible = true;
} else if (isAuthenticated) {
if (passphraseModal.visible) {
passphraseModal.visible = false;
}
if (!securityImageResultReceived) {
commerce.getSecurityImage();
}
if (!keyFilePathIfExistsResultReceived) {
commerce.getKeyFilePathIfExists();
}
if (!balanceReceived) {
commerce.balance();
}
if (!purchasesReceived) {
commerce.inventory();
}
onKeyFilePathIfExistsResult: {
if (path === "" && root.activeView !== "notSetUp") {
root.activeView = "notSetUp";
} else if (path !== "" && root.activeView === "initialize") {
commerce.getSecurityImage();
}
}
@ -85,8 +61,9 @@ Rectangle {
securityImageResultReceived = true;
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
root.activeView = "notSetUp";
} else if (root.securityImageResultReceived && exists && root.keyFilePathIfExistsResultReceived && root.activeView === "initialize") {
} else if (exists && root.activeView === "initialize") {
root.activeView = "checkoutMain";
commerce.getWalletAuthenticatedStatus();
} else if (exists) {
// just set the source again (to be sure the change was noticed)
securityImage.source = "";
@ -94,12 +71,16 @@ Rectangle {
}
}
onKeyFilePathIfExistsResult: {
keyFilePathIfExistsResultReceived = true;
if (path === "" && root.activeView !== "notSetUp") {
root.activeView = "notSetUp";
} else if (root.securityImageResultReceived && root.keyFilePathIfExistsResultReceived && path !== "" && root.activeView === "initialize") {
root.activeView = "checkoutMain";
onWalletAuthenticatedStatusResult: {
if (!isAuthenticated && !passphraseModal.visible) {
passphraseModal.visible = true;
} else if (isAuthenticated) {
if (!balanceReceived) {
commerce.balance();
}
if (!purchasesReceived) {
commerce.inventory();
}
}
}
@ -219,7 +200,6 @@ Rectangle {
securityImageResultReceived = false;
purchasesReceived = false;
balanceReceived = false;
keyFilePathIfExistsResultReceived = false;
commerce.getLoginStatus();
}
}
@ -245,7 +225,7 @@ Rectangle {
}
}
PassphraseModal {
HifiWallet.PassphraseModal {
id: passphraseModal;
z: 998;
visible: false;
@ -256,7 +236,16 @@ Rectangle {
Connections {
onSendSignalToParent: {
sendToScript(msg);
if (msg.method === 'passphraseModal_authSuccess') {
if (!balanceReceived) {
commerce.balance();
}
if (!purchasesReceived) {
commerce.inventory();
}
} else {
sendToScript(msg);
}
}
}
}

View file

@ -28,7 +28,6 @@ Rectangle {
property string activeView: "initialize";
property string referrerURL: "";
property bool securityImageResultReceived: false;
property bool keyFilePathIfExistsResultReceived: false;
property bool purchasesReceived: false;
property bool punctuationMode: false;
// Style
@ -41,35 +40,15 @@ Rectangle {
root.activeView = "needsLogIn";
} else if (isLoggedIn) {
root.activeView = "initialize";
commerce.getPassphraseSetupStatus();
}
}
onPassphraseSetupStatusResult: {
if (!passphraseIsSetup && root.activeView !== "notSetUp") {
root.activeView = "notSetUp";
} else if (passphraseIsSetup && root.activeView === "initialize") {
commerce.getWalletAuthenticatedStatus();
commerce.getKeyFilePathIfExists();
}
}
onWalletAuthenticatedStatusResult: {
if (!isAuthenticated && !passphraseModal.visible) {
passphraseModal.visible = true;
} else if (isAuthenticated) {
if (passphraseModal.visible) {
passphraseModal.visible = false;
}
if (!securityImageResultReceived) {
commerce.getSecurityImage();
}
if (!keyFilePathIfExistsResultReceived) {
commerce.getKeyFilePathIfExists();
}
if (!purchasesReceived) {
commerce.inventory();
}
onKeyFilePathIfExistsResult: {
if (path === "" && root.activeView !== "notSetUp") {
root.activeView = "notSetUp";
} else if (path !== "" && root.activeView === "initialize") {
commerce.getSecurityImage();
}
}
@ -77,8 +56,9 @@ Rectangle {
securityImageResultReceived = true;
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
root.activeView = "notSetUp";
} else if (root.securityImageResultReceived && exists && root.keyFilePathIfExistsResultReceived && root.activeView === "initialize") {
} else if (exists && root.activeView === "initialize") {
root.activeView = "purchasesMain";
commerce.getWalletAuthenticatedStatus();
} else if (exists) {
// just set the source again (to be sure the change was noticed)
securityImage.source = "";
@ -86,12 +66,11 @@ Rectangle {
}
}
onKeyFilePathIfExistsResult: {
keyFilePathIfExistsResultReceived = true;
if (path === "" && root.activeView !== "notSetUp") {
root.activeView = "notSetUp";
} else if (root.securityImageResultReceived && root.keyFilePathIfExistsResultReceived && path !== "" && root.activeView === "initialize") {
root.activeView = "purchasesMain";
onWalletAuthenticatedStatusResult: {
if (!isAuthenticated && !passphraseModal.visible) {
passphraseModal.visible = true;
} else if (isAuthenticated) {
commerce.inventory();
}
}
@ -192,7 +171,6 @@ Rectangle {
Component.onCompleted: {
securityImageResultReceived = false;
purchasesReceived = false;
keyFilePathIfExistsResultReceived = false;
commerce.getLoginStatus();
}
}
@ -218,7 +196,7 @@ Rectangle {
}
}
PassphraseModal {
HifiWallet.PassphraseModal {
id: passphraseModal;
z: 998;
visible: false;
@ -229,7 +207,13 @@ Rectangle {
Connections {
onSendSignalToParent: {
sendToScript(msg);
if (msg.method === 'passphraseModal_authSuccess') {
if (!purchasesReceived) {
commerce.inventory();
}
} else {
sendToScript(msg);
}
}
}
}

View file

@ -31,6 +31,17 @@ Item {
passphraseModalSecurityImage.source = "";
passphraseModalSecurityImage.source = "image://security/securityImage";
}
onWalletAuthenticatedStatusResult: {
submitPassphraseInputButton.enabled = true;
if (!isAuthenticated) {
// Auth failed, show error text
} else {
root.visible = false;
sendSignalToParent({method: 'passphraseModal_authSuccess'});
}
}
}
// This object is always used in a popup.
@ -222,7 +233,8 @@ Item {
width: parent.width/2 - anchors.rightMargin*2;
text: "Submit"
onClicked: {
//commerce.submitWalletPassphrase(passphraseField.text);
submitPassphraseInputButton.enabled = false;
commerce.setPassphrase(passphraseField.text);
}
}
}

View file

@ -40,8 +40,8 @@ Item {
passphrasePageSecurityImage.source = "image://security/securityImage";
}
onPassphraseSetupStatusResult: {
sendMessageToLightbox({method: 'statusResult', status: passphraseIsSetup});
onWalletAuthenticatedStatusResult: {
sendMessageToLightbox({method: 'statusResult', status: isAuthenticated});
}
}
@ -195,7 +195,7 @@ Item {
// Text below TextFields
RalewaySemiBold {
id: passwordReqs;
text: "Passphrase must be at least 4 characters";
text: "Passphrase must be at least 3 characters";
// Text size
size: 16;
// Anchors
@ -252,7 +252,7 @@ Item {
}
function validateAndSubmitPassphrase() {
if (passphraseField.text.length < 4) {
if (passphraseField.text.length < 3) {
setErrorText("Passphrase too short.");
return false;
} else if (passphraseField.text !== passphraseFieldAgain.text) {

View file

@ -26,8 +26,6 @@ Rectangle {
id: root;
property string activeView: "initialize";
property bool securityImageResultReceived: false;
property bool keyFilePathIfExistsResultReceived: false;
property bool keyboardRaised: false;
// Style
@ -40,14 +38,22 @@ Rectangle {
root.activeView = "needsLogIn";
} else if (isLoggedIn) {
root.activeView = "initialize";
commerce.getPassphraseSetupStatus();
commerce.getKeyFilePathIfExists();
}
}
onPassphraseSetupStatusResult: {
if (!passphraseIsSetup && root.activeView !== "notSetUp") {
onKeyFilePathIfExistsResult: {
if (path === "" && root.activeView !== "notSetUp") {
root.activeView = "notSetUp";
} else if (passphraseIsSetup && root.activeView === "initialize") {
} else if (path !== "" && root.activeView === "initialize") {
commerce.getSecurityImage();
}
}
onSecurityImageResult: {
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
root.activeView = "notSetUp";
} else if (exists && root.activeView === "initialize") {
commerce.getWalletAuthenticatedStatus();
}
}
@ -56,33 +62,6 @@ Rectangle {
if (!isAuthenticated && !passphraseModal.visible) {
passphraseModal.visible = true;
} else if (isAuthenticated) {
if (passphraseModal.visible) {
passphraseModal.visible = false;
}
if (!securityImageResultReceived) {
commerce.getSecurityImage();
}
if (!keyFilePathIfExistsResultReceived) {
commerce.getKeyFilePathIfExists();
}
}
}
onSecurityImageResult: {
securityImageResultReceived = true;
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
root.activeView = "notSetUp";
} else if (root.securityImageResultReceived && exists && root.keyFilePathIfExistsResultReceived && root.activeView === "initialize") {
root.activeView = "walletHome";
}
}
onKeyFilePathIfExistsResult: {
keyFilePathIfExistsResultReceived = true;
if (path === "" && root.activeView !== "notSetUp") {
root.activeView = "notSetUp";
} else if (root.securityImageResultReceived && root.keyFilePathIfExistsResultReceived && path !== "" && root.activeView === "initialize") {
root.activeView = "walletHome";
}
}
@ -254,7 +233,11 @@ Rectangle {
Connections {
onSendSignalToParent: {
sendToScript(msg);
if (msg.method === 'passphraseModal_authSuccess') {
root.activeView = "walletHome";
} else {
sendToScript(msg);
}
}
}
}

View file

@ -39,9 +39,9 @@ Rectangle {
}
}
onPassphraseSetupStatusResult: {
onWalletAuthenticatedStatusResult: {
securityImageContainer.visible = false;
if (passphraseIsSetup) {
if (isAuthenticated) {
privateKeysReadyContainer.visible = true;
} else {
choosePassphraseContainer.visible = true;

View file

@ -29,6 +29,40 @@ QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) {
connect(wallet.data(), &Wallet::keyFilePathIfExistsResult, this, &QmlCommerce::keyFilePathIfExistsResult);
}
void QmlCommerce::getLoginStatus() {
emit loginStatusResult(DependencyManager::get<AccountManager>()->isLoggedIn());
}
void QmlCommerce::getKeyFilePathIfExists() {
auto wallet = DependencyManager::get<Wallet>();
wallet->sendKeyFilePathIfExists();
}
void QmlCommerce::getWalletAuthenticatedStatus() {
auto wallet = DependencyManager::get<Wallet>();
emit walletAuthenticatedStatusResult(wallet->walletIsAuthenticatedWithPassphrase());
}
void QmlCommerce::getSecurityImage() {
auto wallet = DependencyManager::get<Wallet>();
wallet->getSecurityImage();
}
void QmlCommerce::chooseSecurityImage(const QString& imageFile) {
auto wallet = DependencyManager::get<Wallet>();
wallet->chooseSecurityImage(imageFile);
}
void QmlCommerce::setPassphrase(const QString& passphrase) {
auto wallet = DependencyManager::get<Wallet>();
wallet->setPassphrase(passphrase);
getWalletAuthenticatedStatus();
}
void QmlCommerce::buy(const QString& assetId, int cost, const QString& buyerUsername) {
auto ledger = DependencyManager::get<Ledger>();
auto wallet = DependencyManager::get<Wallet>();
@ -60,42 +94,7 @@ void QmlCommerce::history() {
ledger->history(wallet->listPublicKeys());
}
void QmlCommerce::chooseSecurityImage(const QString& imageFile) {
auto wallet = DependencyManager::get<Wallet>();
wallet->chooseSecurityImage(imageFile);
}
void QmlCommerce::getSecurityImage() {
auto wallet = DependencyManager::get<Wallet>();
wallet->getSecurityImage();
}
void QmlCommerce::getLoginStatus() {
emit loginStatusResult(DependencyManager::get<AccountManager>()->isLoggedIn());
}
void QmlCommerce::setPassphrase(const QString& passphrase) {
auto wallet = DependencyManager::get<Wallet>();
wallet->setPassphrase(passphrase);
getPassphraseSetupStatus();
}
void QmlCommerce::getPassphraseSetupStatus() {
auto wallet = DependencyManager::get<Wallet>();
// ????? WHAT DO I DO HERE
emit passphraseSetupStatusResult(wallet->getPassphraseIsCached());
}
void QmlCommerce::getWalletAuthenticatedStatus() {
auto wallet = DependencyManager::get<Wallet>();
// ????? WHAT DO I DO HERE
emit walletAuthenticatedStatusResult(wallet->getPassphraseIsCached());
}
void QmlCommerce::getKeyFilePathIfExists() {
auto wallet = DependencyManager::get<Wallet>();
wallet->sendKeyFilePathIfExists();
}
void QmlCommerce::reset() {
auto ledger = DependencyManager::get<Ledger>();

View file

@ -28,30 +28,32 @@ public:
QmlCommerce(QQuickItem* parent = nullptr);
signals:
void loginStatusResult(bool isLoggedIn);
void keyFilePathIfExistsResult(const QString& path);
void securityImageResult(bool exists);
void walletAuthenticatedStatusResult(bool isAuthenticated);
void buyResult(QJsonObject result);
// Balance and Inventory are NOT properties, because QML can't change them (without risk of failure), and
// because we can't scalably know of out-of-band changes (e.g., another machine interacting with the block chain).
void balanceResult(QJsonObject result);
void inventoryResult(QJsonObject result);
void securityImageResult(bool exists);
void loginStatusResult(bool isLoggedIn);
void passphraseSetupStatusResult(bool passphraseIsSetup);
void historyResult(QJsonObject result);
void keyFilePathIfExistsResult(const QString& path);
void walletAuthenticatedStatusResult(bool isAuthenticated);
protected:
Q_INVOKABLE void getLoginStatus();
Q_INVOKABLE void getKeyFilePathIfExists();
Q_INVOKABLE void getSecurityImage();
Q_INVOKABLE void getWalletAuthenticatedStatus();
Q_INVOKABLE void chooseSecurityImage(const QString& imageFile);
Q_INVOKABLE void setPassphrase(const QString& passphrase);
Q_INVOKABLE void buy(const QString& assetId, int cost, const QString& buyerUsername = "");
Q_INVOKABLE void balance();
Q_INVOKABLE void inventory();
Q_INVOKABLE void history();
Q_INVOKABLE void chooseSecurityImage(const QString& imageFile);
Q_INVOKABLE void getSecurityImage();
Q_INVOKABLE void getLoginStatus();
Q_INVOKABLE void setPassphrase(const QString& passphrase);
Q_INVOKABLE void getPassphraseSetupStatus();
Q_INVOKABLE void getWalletAuthenticatedStatus();
Q_INVOKABLE void getKeyFilePathIfExists();
Q_INVOKABLE void reset();
};

View file

@ -342,6 +342,24 @@ bool Wallet::decryptFile(const QString& inputFilePath, unsigned char** outputBuf
return true;
}
bool Wallet::walletIsAuthenticatedWithPassphrase() {
// try to read existing keys if they exist...
// FIXME: initialize OpenSSL elsewhere soon
initialize();
auto publicKey = readPublicKey(keyFilePath().toStdString().c_str());
if (publicKey.size() > 0) {
if (auto key = readPrivateKey(keyFilePath().toStdString().c_str())) {
RSA_free(key);
return true;
}
}
return false;
}
bool Wallet::createIfNeeded() {
if (_publicKeys.count() > 0) return false;

View file

@ -40,6 +40,7 @@ public:
void setPassphrase(const QString& passphrase);
QString* getPassphrase() { return _passphrase; }
bool getPassphraseIsCached() { return !(_passphrase->isEmpty()); }
bool walletIsAuthenticatedWithPassphrase();
void reset();