def login_21(): """ Restore wallet to disk and log in to 21. """ mnemonic = os.environ["TWO1_WALLET_MNEMONIC"] provider = TwentyOneProvider() wallet = Two1Wallet.import_from_mnemonic(provider, mnemonic) if not os.path.exists(os.path.dirname(Two1Wallet.DEFAULT_WALLET_PATH)): os.makedirs(os.path.dirname(Two1Wallet.DEFAULT_WALLET_PATH)) wallet.to_file(Two1Wallet.DEFAULT_WALLET_PATH) # login config = Config() machine_auth = machine_auth_wallet.MachineAuthWallet(wallet) username = os.environ["TWO1_USERNAME"] password = os.environ["TWO1_PASSWORD"] rest_client = _rest_client.TwentyOneRestClient(two1.TWO1_HOST, machine_auth, username) machine_auth_pubkey_b64 = base64.b64encode( machine_auth.public_key.compressed_bytes).decode() payout_address = machine_auth.wallet.current_address rest_client.login(payout_address=payout_address, password=password) config.set("username", username) config.set("mining_auth_pubkey", machine_auth_pubkey_b64) config.save()
def __init__(self): super().__init__() self._logger = logging.getLogger('hello.publish') logging.basicConfig(stream=sys.stdout, level=logging.INFO) self._username = settings.TWO1_USERNAME self._client = rest_client.TwentyOneRestClient(username=self._username, wallet=settings.WALLET)
def set_password(config, machine_auth): """ Upadets the 21 user account password from command line Args: config (Config): config object used for getting .two1 information client (two1.server.rest_client.TwentyOneRestClient) an object for sending authenticated requests to the TwentyOne backend. """ if not config.username: logger.info(uxstring.UxString.login_required) return # use existing username in config rest_client = _rest_client.TwentyOneRestClient(two1.TWO1_HOST, machine_auth, config.username) try: password = click.prompt(uxstring.UxString.set_new_password.format(config.username), hide_input=True, confirmation_prompt=True, type=Password()) try: rest_client.update_password(password) except exceptions.ServerRequestError as ex: if 400 <= ex.status_code < 500: raise exceptions.UnloggedException(ex.data.get('status')) else: raise except click.exceptions.Abort: pass
def test_request_error_paths(mock_wallet, request_side_effect, status_code, data, raised_exception): # creates a machine_auth from a mock wallet machine_auth = machine_auth_wallet.MachineAuthWallet(mock_wallet) rc = rest_client.TwentyOneRestClient("", machine_auth) with mock.patch("two1.server.rest_client.requests.Session.request" ) as mock_request: if request_side_effect: mock_request.side_effect = request_side_effect with pytest.raises(raised_exception): rc._request() else: response = MockHttpResponse(status_code=status_code, data=data) mock_request.return_value = response if raised_exception: with pytest.raises(raised_exception) as ex_info: rc._request() if data: try: json.loads(data) except ValueError: try: json.loads(data) except ValueError: assert 'error' in ex_info.value.message else: assert 'error' in ex_info.value.data else: assert json.loads(data) == ex_info.value.data else: assert rc._request() == response
def get_user_credentials(two1_dir="~/.two1/two1.json"): """ Collect user credentials at CLI. """ with open(os.path.expanduser(two1_dir), "r") as f: username = json.load(f)["username"] try: w = wallet.Wallet() except: logger.info( click.style( "A technical error occured. Please try the previous command again.", fg="magenta")) sys.exit() machine_auth = machine_auth_wallet.MachineAuthWallet(w) rest_client = _rest_client.TwentyOneRestClient(TWO1_HOST, machine_auth, username) address = w.current_address correct_password = False pw = click.prompt(click.style("Please enter your 21 password", fg=PROMPT_COLOR), hide_input=True) while not correct_password: try: rest_client.login(payout_address=address, password=pw) correct_password = True except: pw = click.prompt(click.style( "Incorrect 21 password. Please try again", fg="magenta"), hide_input=True) return username, pw
def __init__(self): """ Constructor for the Rev class. """ self.config = two1_config.Config(two1.TWO1_CONFIG_FILE, None) self.wallet = wallet_utils.get_or_create_wallet(self.config.wallet_path) self.machine_auth = machine_auth_wallet.MachineAuthWallet(self.wallet) self.client = rest_client.TwentyOneRestClient(two1.TWO1_HOST, self.machine_auth, self.config.username)
def create_default_rest_client(): """Return a rest client using default parameters.""" import two1 from two1 import wallet from two1.commands.util import config from two1.server import machine_auth_wallet, rest_client auth = machine_auth_wallet.MachineAuthWallet(wallet.Wallet()) return rest_client.TwentyOneRestClient(two1.TWO1_HOST, auth, config.Config().username)
def parse_config( config_file=two1.TWO1_CONFIG_FILE, config_dict=None, need_wallet_and_account=True, check_update=False, debug=False, ): """Get configuration information that is used to drive all 21 commands. This function is very useful for testing as it builds up several key variables (like the client, wallet, username, and the like) that are used in many commands. The way it does this is by taking in the config_file (typically .two1/two1.json) and the config_dict (a list of key-value pairs to override the config_file, typically an empty dictionary), and then running the logic below. It returns obj which is a dictionary that has Config, Wallet, MachineAuth, and TwentyOneRestClient instances underneath it, as well as a string with the username. The obj is passed down by click to various other commands. You can use this function in any test to instantiate the user's wallet, username, and other variables. """ try: config = two1_config.Config(config_file, config_dict, check_update=check_update) except exceptions.FileDecodeError as e: raise click.ClickException( uxstring.UxString.Error.file_decode.format((str(e)))) wallet, machine_auth, username, client = None, None, None, None if need_wallet_and_account: try: wallet = wallet_utils.get_or_create_wallet(config.wallet_path) except blockchain_exceptions.DataProviderError as err: raise exceptions.Two1Error( 'You have experienced a data provider error: %s ' % err.args) machine_auth = machine_auth_wallet.MachineAuthWallet(wallet) username = account_utils.get_or_create_username(config, machine_auth) client = rest_client.TwentyOneRestClient(two1.TWO1_HOST, machine_auth, config.username) config.username = username obj = dict( config=config, wallet=wallet, machine_auth=machine_auth, username=username, client=client, debug=debug, ) return obj
def login_account(config, machine_auth, username=None, password=None): """ Log in a user into the two1 account Args: config (Config): config object used for getting .two1 information username (str): optional command line arg to skip username prompt password (str): optional command line are to skip password prompt """ # prints the sign up page link when a username is not set and not on a BC if not config.username and not bitcoin_computer.has_mining_chip(): logger.info(uxstring.UxString.signin_title) # uses specifies username or asks for a different one username = username or get_username_interactive() password = password or get_password_interactive() # use existing username in config rest_client = _rest_client.TwentyOneRestClient(two1.TWO1_HOST, machine_auth, username) # get the payout address and the pubkey from the machine auth wallet machine_auth_pubkey_b64 = base64.b64encode( machine_auth.public_key.compressed_bytes).decode() payout_address = machine_auth.wallet.current_address logger.info(uxstring.UxString.login_in_progress.format(username)) try: rest_client.login(payout_address=payout_address, password=password) # handles 401 gracefully except exceptions.ServerRequestError as ex: if ex.status_code == 403 and "error" in ex.data and ex.data[ "error"] == "TO408": email = ex.data["email"] raise exceptions.UnloggedException( click.style(uxstring.UxString.unconfirmed_email.format(email), fg="blue")) elif ex.status_code == 403 or ex.status_code == 404: raise exceptions.UnloggedException( uxstring.UxString.incorrect_password) else: raise ex logger.info(uxstring.UxString.payout_address.format(payout_address)) logger.info(uxstring.UxString.get_started) # Save the new username and auth key config.set("username", username) config.set("mining_auth_pubkey", machine_auth_pubkey_b64) config.save()
def get_rest_client(): """ Helper method to create rest_client. """ with open(os.path.expanduser("~/.two1/two1.json"), "r") as f: username = json.load(f)["username"] try: w = wallet.Wallet() except: logger.info(click.style("A technical error occured. Please try the previous command again.", fg="magenta")) sys.exit() machine_auth = machine_auth_wallet.MachineAuthWallet(w) rest_client = _rest_client.TwentyOneRestClient(TWO1_HOST, machine_auth, username) return rest_client
def __init__(self, wallet, username=None, client=None): """Initialize the bittransfer with wallet and username.""" from two1.server.machine_auth_wallet import MachineAuthWallet from two1.server import rest_client super().__init__() if isinstance(wallet, MachineAuthWallet): self.wallet = wallet else: self.wallet = MachineAuthWallet(wallet) if username is None: self.username = config.Config().username else: self.username = username if client is None: self.client = rest_client.TwentyOneRestClient( two1.TWO1_HOST, self.wallet, self.username) else: self.client = client
def test_check_headers(mock_wallet, device_id, data): # Creates a machine_auth from a mock wallet machine_auth = machine_auth_wallet.MachineAuthWallet(mock_wallet) rc = rest_client.TwentyOneRestClient("", machine_auth) # Forces the rest client _device_id to be parameterized if device_id: rc._device_id = device_id # Gets the encoded amchine auth pub key wallet_pk = base64.b64encode( machine_auth.public_key.compressed_bytes).decode() # Expected header format to be called as an input param into request expected_headers = { 'User-Agent': "21/{}".format(two1.TWO1_VERSION), 'From': "{}@{}".format(wallet_pk, device_id if device_id else "FREE_CLIENT") } # Function only adds content type when there is content if data: expected_headers['Content-Type'] = 'application/json' with mock.patch("two1.server.rest_client.requests.Session.request" ) as mock_request: mock_request.return_value = MockHttpResponse(status_code=200, data=None) rc._request(data=data) call_args = mock_request.call_args kwargs = call_args[1] assert 'headers' in kwargs for key, value in expected_headers.items(): assert key in kwargs['headers'] assert value == kwargs['headers'][key]
def create_account_on_bc(config, machine_auth): """ Creates an account for the current machine auth wallet Args: config (Config): config object used for getting .two1 information machine_auth (MachineAuthWallet): machine auth wallet used for authentication """ # get the payout address and the pubkey from the machine auth wallet machine_auth_pubkey_b64 = base64.b64encode(machine_auth.public_key.compressed_bytes).decode() payout_address = machine_auth.wallet.current_address # Don't attempt to create an account if the user indicates they # already have an account (defaults to No) if click.confirm(uxstring.UxString.already_have_account): logger.info(uxstring.UxString.please_login) sys.exit() logger.info(uxstring.UxString.missing_account) email = None username = None fullname = None while True: if not fullname: fullname = click.prompt(uxstring.UxString.enter_name) if not email: email = click.prompt(uxstring.UxString.enter_email, type=EmailAddress()) # prompts for a username and password if not username: try: logger.info("") username = click.prompt(uxstring.UxString.enter_username, type=Username()) logger.info("") logger.info(uxstring.UxString.creating_account.format(username)) password = click.prompt(uxstring.UxString.set_new_password.format(username), hide_input=True, confirmation_prompt=True, type=Password()) except click.Abort: return try: # change the username of the given username rest_client = _rest_client.TwentyOneRestClient(two1.TWO1_HOST, machine_auth, username) rest_client.account_post(payout_address, email, password, fullname) # Do not continue creating an account because the UUID is invalid except exceptions.BitcoinComputerNeededError: raise except exceptions.ServerRequestError as ex: # handle various 400 errors from the server if ex.status_code == 400: if "error" in ex.data: error_code = ex.data["error"] # email exists if error_code == "TO401": logger.info(uxstring.UxString.email_exists.format(email)) email = None continue # username exists elif error_code == "TO402": logger.info(uxstring.UxString.username_exists.format(username)) username = None continue # unexpected 400 error else: raise exceptions.Two1Error( str(next(iter(ex.data.values()), "")) + "({})".format(ex.status_code)) # handle an invalid username format elif ex.status_code == 404: logger.info(uxstring.UxString.Error.invalid_username) # handle an error where a bitcoin computer is necessary elif ex.status_code == 403: r = ex.data if "detail" in r and "TO200" in r["detail"]: raise exceptions.UnloggedException(uxstring.UxString.max_accounts_reached) else: logger.info(uxstring.UxString.Error.account_failed) username = None # created account successfully else: logger.info(uxstring.UxString.payout_address.format(payout_address)) # save new username and password config.set("username", username) config.set("mining_auth_pubkey", machine_auth_pubkey_b64) config.save() break
# Setup the dashboard from two1.commands import status from two1.commands import log from two1.commands import flush from two1.commands import mine from two1.wallet import Wallet from two1.server.machine_auth_wallet import MachineAuthWallet from two1.server import rest_client from two1.commands.config import Config from two1 import TWO1_HOST wallet = Wallet() host = TWO1_HOST conf = Config() username = Config().username client = rest_client.TwentyOneRestClient(host, MachineAuthWallet(wallet), username) admin = Admin(app, name='Admin', template_mode='bootstrap3') class DashboardView(BaseView): @expose('/', methods=('GET', 'POST')) def dashboard(self): flush_message = "" status_mining = status.status_mining(client) if request.method == 'POST': print(request.form) if request.form['submit'] == 'Flush Earnings': flush_message = self.doFlush() else: if status_mining[
def __init__(self): super().__init__() self._logger = logging.getLogger('deep21.publish') self._username = settings.TWO1_USERNAME self._client = rest_client.TwentyOneRestClient(username=self._username, wallet=settings.WALLET)