Skip to content
Snippets Groups Projects
Select Git revision
  • 4e7aec37ec2e73880d856b818ac373c75ef3b75d
  • main default protected
  • release/1.1
  • encrypt_comments
  • mnemonic_dewif
  • authors_rules
  • 0.14
  • rtd
  • 1.2.1 protected
  • 1.2.0 protected
  • 1.1.1 protected
  • 1.1.0 protected
  • 1.0.0 protected
  • 1.0.0rc1 protected
  • 1.0.0rc0 protected
  • 1.0.0-rc protected
  • 0.62.0 protected
  • 0.61.0 protected
  • 0.60.1 protected
  • 0.58.1 protected
  • 0.60.0 protected
  • 0.58.0 protected
  • 0.57.0 protected
  • 0.56.0 protected
  • 0.55.1 protected
  • 0.55.0 protected
  • 0.54.3 protected
  • 0.54.2 protected
28 results

save_revoke_document.py

Blame
  • login-controllers.js 18.78 KiB
    
    angular.module('cesium.login.controllers', ['cesium.services'])
    
      .controller('LoginModalCtrl', LoginModalController)
    
      .controller('AuthCtrl', AuthController)
    
    ;
    
    
    function LoginModalController($scope, $timeout, $q, $ionicPopover, $window, CryptoUtils, csCrypto, ionicReady,
                                  UIUtils, BMA, Modals, csConfig, csSettings, Device, parameters) {
      'ngInject';
    
      parameters = parameters || {};
    
      // Demo mode: force PUBKEY method
      if (csConfig.demo) {
        parameters.method = 'PUBKEY';
      }
    
      $scope.computing = false;
      $scope.pubkey = null;
      $scope.formData = {};
      $scope.showSalt = false;
      $scope.showPassword = false;
      $scope.showPubkey = false;
      $scope.showComputePubkeyButton = false;
      $scope.autoComputePubkey = false;
      $scope.pubkeyPattern = '^(:?{0}|{1})$'.format(BMA.constants.regexp.PUBKEY, BMA.constants.regexp.PUBKEY_WITH_CHECKSUM);
    
      $scope.isAuth = parameters.auth;
      $scope.okText = parameters.okText;
      $scope.title = parameters.title || ($scope.isAuth ? 'AUTH.TITLE' : 'LOGIN.TITLE');
      $scope.showMethods = angular.isDefined(parameters.showMethods) ? parameters.showMethods : true;
      $scope.showNewAccountLink = angular.isDefined(parameters.showNewAccountLink) ? parameters.showNewAccountLink : true;
      $scope.expectedPubkey = parameters.expectedPubkey;
      $scope.expectedUid = parameters.uid;
    
      $scope.scryptParamsValues = _.keys(CryptoUtils.constants.SCRYPT_PARAMS)
        .reduce(function(res, key) {
          return res.concat({id: key, label: 'LOGIN.SCRYPT.' + key, params: CryptoUtils.constants.SCRYPT_PARAMS[key]});
        }, [{id: 'USER', label: 'LOGIN.SCRYPT.USER', params: {}}]);
    
      // modal init
      $scope.init = function() {
    
        ionicReady().then(function(){
          // Should auto-compute pubkey ?
          $scope.autoComputePubkey = ionic.Platform.grade.toLowerCase()==='a' &&
            !UIUtils.screen.isSmall();
        });
    
        // Init remember me
        $scope.formData.rememberMe = csSettings.data.rememberMe;
    
        // Init keep auth, from idle time
        $scope.formData.keepAuthIdle = csSettings.data.keepAuthIdle;
        $scope.formData.keepAuth = ($scope.formData.keepAuthIdle == csSettings.constants.KEEP_AUTH_IDLE_SESSION);
    
        // Init method
        var method = parameters.method || csSettings.data.login && csSettings.data.login.method || 'SCRYPT_DEFAULT';
        var params = csSettings.data.login && csSettings.data.login.params;
        // used default method, when PUBKEY + auth, or SCAN, or if ask for 'default'
        if (($scope.isAuth && method === 'PUBKEY') || (method === 'SCAN') || (method === 'default')) {
          method = 'SCRYPT_DEFAULT';
        }
        $scope.changeMethod(method, params);
      };
    
      // modal enter
      $scope.enter = function() {
        UIUtils.loading.hide();
        // Ink effect
        UIUtils.ink({selector: '.modal-login .ink'});
      };
      $scope.$on('modal.shown', $scope.enter);
    
      // modal leave
      $scope.leave = function() {
        $scope.formData = {};
        $scope.computing = false;
        $scope.pubkey = null;
        $scope.methods = [];
      };
      $scope.$on('modal.hide', $scope.leave);
    
      // Login form submit
      $scope.doLogin = function(skipForm) {
        var method = $scope.formData.method;
    
        if(!$scope.form.$valid && method !== 'SCAN') return;
    
        // removeIf(no-device)
        Device.keyboard.close();
        // endRemoveIf(no-device)
    
        var keepAuthIdle = $scope.formData.keepAuthIdle;
        var promise;
    
        // Scrypt
        if (method === 'SCRYPT_DEFAULT' || method === 'SCRYPT_ADVANCED') {
          if (!$scope.formData.username || !$scope.formData.password) return;
          var scryptPrams = $scope.formData.scrypt && $scope.formData.scrypt.params;
          UIUtils.loading.show();
          promise = csCrypto.ready()
            .then(function() {
              return csCrypto.scrypt.keypair($scope.formData.username, $scope.formData.password, scryptPrams);
            })
            .then(function(keypair) {
              if (!keypair) return UIUtils.loading.hide(10);
              var pubkey = csCrypto.util.encode_base58(keypair.signPk);
              // Check pubkey
              if (parameters.expectedPubkey && parameters.expectedPubkey != pubkey) {
                $scope.pubkey = pubkey;
                $scope.showPubkey = true;
                $scope.pubkeyError = true;
                return UIUtils.loading.hide(10);
              }
    
              $scope.pubkeyError = false;
    
              return {
                pubkey: pubkey,
                keypair: keypair,
                params: ($scope.formData.scrypt && $scope.formData.scrypt.id != 'SCRYPT_DEFAULT') ? scryptPrams : undefined
              };
            })
            .catch(UIUtils.onError('ERROR.CRYPTO_UNKNOWN_ERROR'));
        }
    
        // File
        else if (method === 'FILE') {
          if (!$scope.formData.file || !$scope.formData.file.valid || !$scope.formData.file.pubkey) return;
    
          // If checkbox keep auth checked: set idle time to session
          keepAuthIdle = ($scope.formData.keepAuth && csSettings.constants.KEEP_AUTH_IDLE_SESSION) || keepAuthIdle;
    
          promise =
            UIUtils.loading.show()
            .then(function() {
              return $scope.readKeyFile($scope.formData.file, {
                withSecret: ($scope.isAuth || $scope.formData.keepAuth)
              });
            })
            .then(function(keypair) {
              if (!keypair) return UIUtils.loading.hide(10);
              var pubkey = csCrypto.util.encode_base58(keypair.signPk);
    
              // Check pubkey
              if (parameters.expectedPubkey && parameters.expectedPubkey != pubkey) {
                $scope.formData.file.valid = false;
                return UIUtils.loading.hide(10);
              }
    
              $scope.pubkeyError = false;
    
              return {
                pubkey: pubkey,
                keypair: keypair
              };
            })
            .catch(UIUtils.onError('ERROR.AUTH_FILE_ERROR'));
        }
    
        // Pubkey
        else if (method === 'PUBKEY') {
          var pubkey = $scope.formData.pubkey && $scope.formData.pubkey.trim();
          var uid = $scope.formData.uid && $scope.formData.uid.trim() || undefined;
          if (!pubkey) return;
          var matches = BMA.regexp.PUBKEY.exec(pubkey);
          // valid pubkey: use it
          if (matches) {
            promise = UIUtils.loading.show()
              .then(function() {
                return {
                  pubkey: pubkey,
                  uid : uid
                };
              });
          }
    
          // Check checksum
          else {
    
            matches = BMA.regexp.PUBKEY_WITH_CHECKSUM.exec(pubkey);
            if (matches) {
    
              pubkey = matches[1];
              var checksum = matches[2];
              var expectedChecksum = csCrypto.util.pkChecksum(pubkey);
              if (checksum != expectedChecksum) {
                $scope.form.pubkey.$error = {checksum: true};
              }
              else {
                promise = UIUtils.loading.show()
                  .then(function() {
                    return {
                      pubkey: pubkey,
                      uid : uid
                    };
                  });
              }
            }
            // Not a pubkey: launch search on
            else {
              return $scope.showWotLookupModal(pubkey);
            }
          }
        }
    
        // Scan QR code
        else if (method === 'SCAN') {
          var valid = $scope.formData.pubkey && (!$scope.isAuth || !!$scope.formData.keypair);
          if (!valid) return;
    
          promise = UIUtils.loading.show()
            .then(function() {
              return {
                pubkey: $scope.formData.pubkey,
                keypair: $scope.formData.keypair
              };
            });
        }
    
        if (!promise) {
          console.warn('[login] unknown method: ', method);
          return;
        }
    
        return promise.then(function(res) {
          if (!res) return;
    
          // Update settings (if need)
          var rememberMeChanged = !angular.equals(csSettings.data.rememberMe, $scope.formData.rememberMe);
          var keepAuthIdleChanged = !angular.equals(csSettings.data.keepAuthIdle, keepAuthIdle);
          var methodChanged = !angular.equals(csSettings.data.login && csSettings.data.login.method, method);
          var paramsChanged = !angular.equals(csSettings.data.login && csSettings.data.login.params, res.params);
          if (rememberMeChanged || keepAuthIdleChanged || methodChanged || paramsChanged) {
            csSettings.data.rememberMe = $scope.formData.rememberMe;
            csSettings.data.keepAuthIdle = keepAuthIdle;
            csSettings.data.useLocalStorage = csSettings.data.rememberMe ? true : csSettings.data.useLocalStorage;
            csSettings.data.login = csSettings.data.login || {};
            csSettings.data.login.method = method;
            csSettings.data.login.params = res.params;
            $timeout(csSettings.store, 500);
          }
    
          if (parameters.success) {
            parameters.success($scope.formData);
          }
    
          // hide loading
          if (parameters.silent) {
            UIUtils.loading.hide();
          }
    
          // Return result then close
          return $scope.closeModal(res);
        });
      };
    
      $scope.onScryptFormChanged = function() {
        if ($scope.computing) return; // avoid multiple call
        $scope.pubkey = null;
        $scope.pubkeyError = false;
        $scope.showPubkey = !!$scope.formData.username && !!$scope.formData.password;
        if ($scope.autoComputePubkey && $scope.showPubkey) {
          $scope.computePubkey();
          $scope.showComputePubkeyButton = false;
        }
        else {
          $scope.showComputePubkeyButton = !$scope.autoComputePubkey && $scope.showPubkey;
        }
      };
      $scope.$watch('formData.username + formData.password', $scope.onScryptFormChanged, true);
    
      $scope.computePubkey = function() {
        $scope.showComputePubkeyButton = false;
        $scope.computing = true;
        $scope.pubkey = null;
        return $timeout(function() {
          var salt = $scope.formData.username;
          var pwd = $scope.formData.password;
          var scryptPrams = $scope.formData.scrypt && $scope.formData.scrypt.params;
          return csCrypto.ready()
            .then(function() {
              return csCrypto.scrypt.pubkey(salt, pwd, scryptPrams);
            })
            .then(function (pubkey) {
    
              // If model has changed before the response, then retry
              if (salt !== $scope.formData.username || pwd !== $scope.formData.password) {
                return $scope.computePubkey();
              }
    
              $scope.pubkey = pubkey;
              if ($scope.expectedPubkey && $scope.expectedPubkey != $scope.pubkey) {
                $scope.pubkeyError = true;
              }
    
              $scope.computing = false;
            }
          )
          .catch(function (err) {
            UIUtils.onError('ERROR.CRYPTO_UNKNOWN_ERROR')(err);
            $scope.computing = false;
            $scope.autoComputePubkey = false; // Avoid a infinite loop (computePubkey -> onScryptFormChanged -> computePubkey)
            $scope.onScryptFormChanged();
          });
        }, 100);
      };
    
      $scope.showJoinModal = function() {
        $scope.closeModal();
        $timeout(function() {
          Modals.showJoin();
        }, 300);
      };
    
      $scope.showAccountSecurityModal = function() {
        $scope.closeModal();
        $timeout(function() {
          Modals.showAccountSecurity();
        }, 300);
      };
    
      $scope.showHelpModal = function(parameters) {
        return Modals.showHelp(parameters);
      };
    
      $scope.toggleShowSalt = function() {
        console.debug('[login] Toggle showSalt');
        $scope.showSalt = !$scope.showSalt;
      };
    
      $scope.doScan = function() {
        if ($scope.computing) return;
    
        $scope.computing = true;
        $scope.formData.pubkey = null;
        $scope.formData.keypair = null;
    
        // Run scan cordova plugin, on device
        return Device.barcode.scan()
          .then(function(data) {
            if (!data) return;
    
            // Skip simple parsing, if auth if need
            if ($scope.isAuth) return $q.when(data);
    
            // Try to parse as an URI
            return BMA.uri.parse(data)
              .then(function (res) {
                if (!res || !res.pubkey) throw {message: 'ERROR.SCAN_UNKNOWN_FORMAT'};
                // If simple pubkey
                return res;
              })
              .catch(function(err) {
                console.debug('[login] Error while parsing as URI: ' + (err && err.message || err));
                return data;
              });
          })
          .then(function(data) {
            if (!data) return;
            // Parse success: continue
            if (data && data.pubkey) return data;
    
            // Try to read as WIF format
            return csCrypto.keyfile.parseData(data, {silent: true})
              .then(function(keypair) {
                if (!keypair || !keypair.signPk || !keypair.signSk) throw {message: 'ERROR.SCAN_UNKNOWN_FORMAT'}; // rethrow an error
    
                var pubkey = CryptoUtils.base58.encode(keypair.signPk);
    
                // Login using keypair
                return {
                  pubkey: pubkey,
                  keypair: keypair
                };
              })
              // Unknown format (nor URI, nor WIF/EWIF)
              .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT'));
          })
          .then(function(res) {
            if (!res || !res.pubkey) return; // no data
    
            $scope.pubkeyError = $scope.expectedPubkey && $scope.expectedPubkey != res.pubkey;
            $scope.formData.pubkey = res.pubkey;
            $scope.formData.keypair = res.keypair;
          })
          .then(function() {
            $scope.computing = false;
            UIUtils.loading.hide(10);
          })
          .catch(function(err) {
            $scope.computing = false;
            UIUtils.onError('ERROR.SCAN_FAILED')(err);
          });
      };
    
      $scope.changeMethod = function(method, params){
        $scope.hideMethodsPopover();
    
        if (method !== 'PUBKEY' && csConfig.demo) {
          return UIUtils.alert.demo();
        }
    
        if (!method || method === $scope.formData.method) return; // same method
    
        console.debug("[login] method is: " + method);
        $scope.formData.method = method;
        $scope.formData.uid = null;
    
        if ($scope.form) {
          // hide form's fields errors on the form
          delete $scope.form.$submitted;
        }
    
        // Scrypt (advanced or not)
        if (method === 'SCRYPT_DEFAULT' || method === 'SCRYPT_ADVANCED') {
          $scope.pubkey = null;
    
    
          // Search scrypt object
          var scrypt;
          if (params) {
            scrypt = _.find($scope.scryptParamsValues, function(item){
                return item.params && angular.equals(item.params, params);
              });
            if (!scrypt) {
              scrypt = _.findWhere($scope.scryptParamsValues, {id: 'USER'}) || {};
              scrypt.params = params;
            }
          }
          else {
            scrypt = _.findWhere($scope.scryptParamsValues, {id: 'DEFAULT'});
          }
          $scope.changeScrypt(scrypt);
    
          $scope.autoComputePubkey = $scope.autoComputePubkey && (method === 'SCRYPT_DEFAULT');
        }
        else if (method === 'SCAN') {
          return $scope.doScan();
        }
        else {
          $scope.formData.username = null;
          $scope.formData.password = null;
          $scope.formData.pubkey = null;
          $scope.pubkey = null;
          $scope.computing = false;
        }
      };
    
      $scope.changeScrypt = function(scrypt) {
        // Protect params against changes
        $scope.formData.scrypt = angular.copy(scrypt||{});
        $scope.onScryptFormChanged();
      };
    
      $scope.readKeyFile = function(file, options) {
        options = options || {};
    
        options.password = options.password || $scope.formData.file.password || function() {
          $scope.formData.file.password = undefined;
          return Modals.showPassword({
                title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE',
                subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP',
                error: options.error,
                scope: $scope
              })
              .then(function (password) {
                // Remember password (for validation)
                $scope.formData.file.password = password;
                // Timeout is need to force popup to be hide
                return $timeout(function() {
                  return password;
                }, 150);
              });
          };
    
        return csCrypto.keyfile.read($scope.formData.file, options)
          .catch(function(err) {
            $scope.formData.file.password = undefined;
            if (err === 'CANCELLED') {
              UIUtils.loading.hide(10);
            }
            if (err && err.ucode == csCrypto.errorCodes.BAD_PASSWORD) {
              // Recursive call
              return $scope.readKeyFile($scope.formData.file, {withSecret: options.withSecret, error: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_PASSWORD'});
            }
            throw err;
          });
      };
    
      $scope.onFileChanged = function(file) {
        if (!file || !file.fileData) {
          $scope.validatingFile = false;
          return; // Skip
        }
        $scope.formData.file = {
          name: file.fileData.name,
          size: file.fileData.size,
          content: file.fileContent
        };
        $scope.validatingFile = true;
        $timeout(function() {
          console.debug("[login] key file changed: ", $scope.formData.file);
          $scope.validatingFile = true;
    
          return $scope.readKeyFile($scope.formData.file, {withSecret: false, password: $scope.formData.file.password})
            .then(function(keypair) {
              if (!keypair || !keypair.signPk) {
                $scope.formData.file.valid = false;
                $scope.formData.file.pubkey = undefined;
              }
              else {
                $scope.formData.file.pubkey = CryptoUtils.util.encode_base58(keypair.signPk);
                $scope.formData.file.valid = !$scope.expectedPubkey || $scope.expectedPubkey === $scope.formData.file.pubkey;
                $scope.validatingFile = false;
              }
    
            })
            .catch(function(err) {
              if (err && err === 'CANCELLED') {
                $scope.removeKeyFile();
                return;
              }
              $scope.validatingFile = false;
              $scope.formData.file.valid = false;
              $scope.formData.file.pubkey = undefined;
              UIUtils.onError('ERROR.AUTH_FILE_ERROR')(err);
            });
        });
      };
    
      $scope.removeKeyFile = function() {
        $scope.formData.file = undefined;
      };
    
      /* -- modals -- */
    
      $scope.showWotLookupModal = function(searchText) {
        return Modals.showWotLookup({q: searchText})
          .then(function(res){
            if (res && res.pubkey) {
              $scope.formData.pubkey = res.pubkey;
              $scope.formData.uid = res.uid || undefined;
              return $timeout($scope.doLogin, 300);
            }
          });
      };
    
      /* -- popover -- */
      $scope.showMethodsPopover = function(event) {
        if (event.defaultPrevented) return;
        UIUtils.popover.show(event, {
          templateUrl :'templates/login/popover_methods.html',
          scope: $scope,
          autoremove: true,
          afterShow: function(popover) {
            $scope.methodsPopover = popover;
            UIUtils.ink({selector: '.popover-login-methods .item'});
          }
        });
      };
    
      $scope.hideMethodsPopover = function() {
        if ($scope.methodsPopover) {
          $scope.methodsPopover.hide();
          $scope.methodsPopover = null;
        }
      };
    
      // Default action
      $scope.init();
    
    
      // TODO : for DEV only
      /*$timeout(function() {
        $scope.formData = {
          method: 'SCRYPT_DEFAULT',
          username: 'abc',
          password: 'def'
        };
        $scope.form = {$valid:true};
    
        $timeout($scope.doLogin, 500);
      }, 900); */
    }
    
    
    function AuthController($scope, $controller, csConfig){
    
      var config = angular.copy(csConfig);
      config.demo = false;
      config.readonly = false;
    
      // Initialize the super class and extend it.
      angular.extend(this, $controller('LoginModalCtrl', {$scope: $scope, parameters: {auth: true}, csConfig: config}));
    
      $scope.setForm = function(form) {
        $scope.form = form;
      };
    
    }