Skip to content

Commit

Permalink
[#10195] Delete multiaccount
Browse files Browse the repository at this point in the history
  • Loading branch information
rasom committed Jul 28, 2020
1 parent 4254dbc commit 10a8147
Show file tree
Hide file tree
Showing 14 changed files with 269 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -504,10 +504,17 @@ public void run() {
StatusThreadPoolExecutor.getInstance().execute(r);
}

public String getKeyStorePath(String keyUID) {
final String commonKeydir = pathCombine(this.getNoBackupDirectory(), "/keystore");
final String keydir = pathCombine(commonKeydir, keyUID);

return keydir;
}

public void migrateKeyStoreDir(final String accountData, final String password) {
try {
final String commonKeydir = pathCombine(this.getNoBackupDirectory(), "/keystore");
final String keydir = pathCombine(commonKeydir, getKeyUID(accountData));
final String keydir = this.getKeyStorePath(this.getKeyUID(accountData));
Log.d(TAG, "before migrateKeyStoreDir " + keydir);

File keydirFile = new File(keydir);
Expand Down Expand Up @@ -1183,6 +1190,27 @@ public void run() {
StatusThreadPoolExecutor.getInstance().execute(r);
}

@ReactMethod
public void deleteMultiaccount(final String keyUID, final Callback callback) {
Log.d(TAG, "deleteMultiaccount");
if (!checkAvailability()) {
callback.invoke(false);
return;
}

final String keyStoreDir = this.getKeyStorePath(keyUID);
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.deleteMultiaccount(keyUID, keyStoreDir);

callback.invoke(res);
}
};

StatusThreadPoolExecutor.getInstance().execute(r);
}

@ReactMethod(isBlockingSynchronousMethod = true)
public String generateAlias(final String seed) {
return Statusgo.generateAlias(seed);
Expand Down
25 changes: 24 additions & 1 deletion modules/react-native-status/ios/RCTStatus/RCTStatus.m
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,17 @@ - (void)handleSignal:(NSString *)signal
#endif
}

//////////////////////////////////////////////////////////////////// multiAccountImportPrivateKey
RCT_EXPORT_METHOD(deleteMultiaccount:(NSString *)keyUID
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"MultiAccountImportPrivateKey() method called");
#endif
NSURL *multiaccountKeystoreDir = [self getKeyStoreDir:keyUID];
NSString *result = StatusgoDeleteMultiaccount(keyUID, multiaccountKeystoreDir.path);
callback(@[result]);
}

//////////////////////////////////////////////////////////////////// multiAccountGenerateAndDeriveAddresses
RCT_EXPORT_METHOD(multiAccountGenerateAndDeriveAddresses:(NSString *)json
callback:(RCTResponseSenderBlock)callback) {
Expand Down Expand Up @@ -440,6 +451,18 @@ -(NSString *) prepareDirAndUpdateConfig:(NSString *)config
NSLog(@"%@", result);
}

- (NSURL *) getKeyStoreDir:(NSString *)keyUID {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];

NSURL *oldKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
NSURL *multiaccountKeystoreDir = [oldKeystoreDir URLByAppendingPathComponent:keyUID];

return multiaccountKeystoreDir;
}

- (void) migrateKeystore:(NSString *)accountData
password:(NSString *)password {
NSFileManager *fileManager = [NSFileManager defaultManager];
Expand All @@ -449,7 +472,7 @@ - (void) migrateKeystore:(NSString *)accountData

NSString *keyUID = [self getKeyUID:accountData];
NSURL *oldKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
NSURL *multiaccountKeystoreDir = [oldKeystoreDir URLByAppendingPathComponent:keyUID];
NSURL *multiaccountKeystoreDir = [self getKeyStoreDir:keyUID];

NSArray *keys = [fileManager contentsOfDirectoryAtPath:multiaccountKeystoreDir.path error:nil];
if (keys.count == 0) {
Expand Down
12 changes: 12 additions & 0 deletions src/quo/components/separator.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(ns quo.components.separator
(:require [quo.react-native :as react]
[quo.design-system.colors :as colors]))

(defn separator [{:keys [color style]}]
[react/view
{:style
(merge
style
{:background-color (colors/get-color (or color :ui-01))
:align-self :stretch
:height 1})}])
6 changes: 5 additions & 1 deletion src/quo/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
[quo.components.list.footer :as list-footer]
[quo.components.list.item :as list-item]
[quo.components.controls.view :as controls]
[quo.components.bottom-sheet.view :as bottom-sheet]))
[quo.components.bottom-sheet.view :as bottom-sheet]
[quo.components.separator :as separator]
[quo.design-system.colors :as colors]))

(def text text/text)
(def header header/header)
Expand All @@ -28,3 +30,5 @@
(def safe-area-provider safe-area/provider)
(def safe-area-consumer safe-area/consumer)
(def safe-area-view safe-area/view)
(def separator separator/separator)
(def get-color colors/get-color)
3 changes: 3 additions & 0 deletions src/quo/design_system/colors.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,6 @@
:backdrop "rgba(0,0,0,0.4)"})

(def theme (reagent/atom light-theme))

(defn get-color [color]
(get @theme color))
3 changes: 2 additions & 1 deletion src/status_im/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@
status-im.utils.universal-links.events
status-im.search.core
status-im.ui.screens.profile.events
status-im.chat.models.images))
status-im.chat.models.images
status-im.ui.screens.privacy-and-security-settings.events))

;; init module
(handlers/register-handler-fx
Expand Down
7 changes: 7 additions & 0 deletions src/status_im/native_module/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -357,3 +357,10 @@
[mnemonic callback]
(log/debug "[native-module] validate-mnemonic")
(.validateMnemonic ^js (status) mnemonic callback))

(defn delete-multiaccount
"Delete multiaccount from database, deletes multiaccount's database and
key files."
[key-uid callback]
(log/debug "[native-module] delete-multiaccount")
(.deleteMultiaccount ^js (status) key-uid callback))
3 changes: 3 additions & 0 deletions src/status_im/subs.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@
;; keycard
(reg-root-key-sub :keycard/new-account-sheet? :keycard/new-account-sheet?)

;; delete profile
(reg-root-key-sub :delete-profile/error :delete-profile/error)

;;GENERAL ==============================================================================================================

(re-frame/reg-sub
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
(ns status-im.ui.screens.privacy-and-security-settings.delete-profile
(:require [status-im.ui.components.react :as react]
[quo.core :as quo]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[re-frame.core :as re-frame]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.components.styles :as components.styles]
[status-im.i18n :as i18n]
[reagent.core :as reagent]
[status-im.utils.security :as security]
[status-im.ui.screens.privacy-and-security-settings.events :as delete-profile]))

(defn valid-password? [password]
(>= (count password) 6))

(defn keycard-pin []
#_(let [pin @(re-frame/subscribe [:keycard/pin])
step @(re-frame/subscribe [:keycard/pin-enter-step])
status @(re-frame/subscribe [:keycard/pin-status])
pin-retry-counter @(re-frame/subscribe [:keycard/pin-retry-counter])
puk-retry-counter @(re-frame/subscribe [:keycard/puk-retry-counter])
error-label @(re-frame/subscribe [:keycard/pin-error-label])]
[pin.views/pin-view
{:pin pin
:status status
:retry-counter pin-retry-counter
:error-label error-label
:step :current}]))

(defn delete-profile []
(let [password (reagent/atom nil)
text-input-ref (atom nil)]
(fn []
(let [keycard? @(re-frame/subscribe [:keycard-multiaccount?])
multiaccount @(re-frame/subscribe [:multiaccount])
error @(re-frame/subscribe [:delete-profile/error])]
(when (and @text-input-ref error (not @password))
(.clear ^js @text-input-ref))
[react/view components.styles/flex
[topbar/topbar {:modal? true}]
[react/view
{:style {:flex 1
:justify-content :space-between}}
[react/scroll-view {:style {:flex 1}}
[react/view {:style {:align-items :center}}
[quo/text {:weight :bold
:size :x-large}
(i18n/label :t/delete-profile)]]
[quo/list-item
{:title (multiaccounts/displayed-name multiaccount)
:icon [chat-icon.screen/contact-icon-contacts-tab
(multiaccounts/displayed-photo multiaccount)]}]
[quo/text {:style {:margin-horizontal 24}
:align :center
:color :negative}
(i18n/label :t/delete-profile-warning)]
(if keycard?
[keycard-pin]
[quo/text-input
{:style {:margin-horizontal 36
:margin-top 36}
:show-cancel false
:secure-text-entry true
:return-key-type :next
:on-submit-editing nil
:auto-focus true
:on-change-text #(reset! password (security/mask-data %))
:bottom-value 36
:get-ref #(reset! text-input-ref %)
:error (when (and error (not @password))
(if (= :wrong-password error)
(i18n/label :t/wrong-password)
(str error)))}])]
(when-not keycard?
[react/view {:style {:align-items :center}}
[quo/separator]
[react/view
{:style {:margin-vertical 8}}
[quo/button {:on-press #(do
(re-frame/dispatch
[::delete-profile/delete-profile @password])
(reset! password nil))
:theme :negative
:disabled ((complement valid-password?) @password)}
(i18n/label :t/delete-profile)]]])]]))))
67 changes: 67 additions & 0 deletions src/status_im/ui/screens/privacy_and_security_settings/events.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
(ns status-im.ui.screens.privacy-and-security-settings.events
(:require [status-im.utils.fx :as fx]
[re-frame.core :as re-frame]
[status-im.utils.security :as security]
[status-im.native-module.core :as status]
[status-im.ethereum.core :as ethereum]
[status-im.utils.types :as types]
[taoensso.timbre :as log]
[clojure.string :as clojure.string]
[status-im.i18n :as i18n]))

(defn safe-blank? [s]
(or (not s)
(clojure.string/blank? s)))

(re-frame/reg-fx
::delete-profile
(fn [{:keys [address key-uid callback masked-password]}]
(let [hashed-password
(-> masked-password
security/safe-unmask-data
ethereum/sha3)]
(status/verify
address
hashed-password
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
(log/info "[delete-profile] verify-password" result error)
(if-not (safe-blank? error)
(callback :wrong-password nil)
(status/delete-multiaccount
key-uid
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
(callback error nil)))))))))))

(fx/defn delete-profile
{:events [::delete-profile]}
[{:keys [db] :as cofx} masked-password]
(log/info "[delete-profile] delete")
(let [{:keys [key-uid wallet-root-address]} (:multiaccount db)]
{:db (dissoc db :delete-profile/error)
::delete-profile
{:masked-password masked-password
:key-uid key-uid
:address wallet-root-address
:callback
(fn [error result]
(log/info "[delete-profile] callback" error)
(if (safe-blank? error)
(re-frame/dispatch [::on-delete-profile-success result])
(re-frame/dispatch [::on-delete-profile-failure error])))}}))

(fx/defn on-delete-profile-success
{:events [::on-delete-profile-success]}
[cofx]
(log/info "[delete-profile] on-success")
{:utils/show-popup
{:title (i18n/label :t/profile-deleted-title)
:content (i18n/label :t/profile-deleted-content)
:on-dismiss #(re-frame/dispatch [:logout])}})

(fx/defn on-delete-profile-failure
{:events [::on-delete-profile-failure]}
[{:keys [db]} error]
(log/info "[delete-profile] on-failure" error)
{:db (assoc db :delete-profile/error error)})
27 changes: 17 additions & 10 deletions src/status_im/ui/screens/privacy_and_security_settings/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@
[status-im.utils.platform :as platform])
(:require-macros [status-im.utils.views :as views]))

(defn separator []
[quo/separator {:style {:margin-vertical 8}}])

(views/defview privacy-and-security []
(views/letsubs [{:keys [mnemonic preview-privacy?]} [:multiaccount]
supported-biometric-auth [:supported-biometric-auth]
auth-method [:auth-method]]
auth-method [:auth-method]
keycard? [:keycard-multiaccount?]]
[react/view {:flex 1 :background-color colors/white}
[topbar/topbar {:title :t/privacy-and-security}]
[react/scroll-view {:padding-vertical 8}
Expand All @@ -34,9 +38,7 @@
:accessory :switch
:on-press #(re-frame/dispatch [:multiaccounts.ui/biometric-auth-switched
((complement boolean) (= auth-method "biometric"))])}])
[react/view {:margin-vertical 8
:background-color colors/gray-lighter
:height 1}]
[separator]
;; TODO - uncomment when implemented
;; {:size :small
;; :title (i18n/label :t/change-password)
Expand All @@ -61,9 +63,14 @@
:on-press #(re-frame/dispatch
[:multiaccounts.ui/preview-privacy-mode-switched
((complement boolean) preview-privacy?)])}]

(comment
{:container-margin-top 8
:size :small
:title :t/delete-my-account
:theme :negative})]]))
;; TODO(rasom): remove this condition when kk support will be added
(when-not keycard?
[separator])
(when-not keycard?
[quo/list-item
{:size :small
:theme :negative
:title (i18n/label :t/delete-my-profile)
:on-press #(re-frame/dispatch [:navigate-to :delete-profile])
:accessibility-label :dapps-permissions-button
:chevron true}])]]))
7 changes: 6 additions & 1 deletion src/status_im/ui/screens/routing/profile_stack.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
[status-im.ui.screens.keycard.settings.views :as keycard.settings]
[status-im.ui.components.tabbar.styles :as tabbar.styles]
[status-im.ui.screens.routing.core :as navigation]
[status-im.ui.screens.appearance.views :as appearance]))
[status-im.ui.screens.appearance.views :as appearance]
[status-im.ui.screens.privacy-and-security-settings.delete-profile :as delete-profile]))

(defonce stack (navigation/create-stack))

Expand Down Expand Up @@ -115,6 +116,10 @@
:component profile.seed/backup-seed}
{:name :tribute-to-talk
:component tr-to-talk/tribute-to-talk}
{:name :delete-profile
:transition :presentation-ios
:insets {:bottom true}
:component delete-profile/delete-profile}
;; {:name:my-profile-ext-settings
;; :component}

Expand Down
6 changes: 3 additions & 3 deletions status-go-version.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im",
"repo": "status-go",
"version": "v0.55.1",
"commit-sha1": "6d5a93287b2c1b4d4d5d1178a3ecec870bf18b9e",
"src-sha256": "1wly0km9bxxv1wwj6jchqh4d4x2m86fxrdqixjzldy70vl6qbyqa"
"version": "v0.55.2",
"commit-sha1": "0b3cdf7362bbdf9ba7fc11da803105f9417dfbac",
"src-sha256": "1vq3z150p0fbwjc1mqmi8lz4vg28dzqhlpsn7kar8j5z4rx5z5hn"
}
Loading

0 comments on commit 10a8147

Please sign in to comment.