def disconnect(self, name): """Disconnect from named VPN.""" connections = self.filter_connections(name=name, active=True) for c in connections: log.info(u'disconnecting "%s" ...', c.name) cmd = self.program + ['disconnect', c.name] run_command(cmd)
def disconnect(self, name): """Disconnect from named VPN.""" connections = self.filter_connections(name=name, active=True) for c in connections: log.info(u'disconnecting "%s" ...', c.name) cmd = self.program + ['stop', c.name] run_command(cmd)
def connect(self, name): """Connect to named VPN.""" connections = self.filter_connections(name=name, active=False) for c in connections: log.info(u'connecting "%s" ...', c.name) cmd = self.program + ['start', c.name] run_command(cmd)
def connect(self, name): """Connect to named VPN.""" connections = self.filter_connections(name=name, active=False) for c in connections: log.info(u'connecting "%s" ...', c.name) cmd = self.program + ['connect', c.name] run_command(cmd)
def test_run_command(): """Run command.""" data = [ # command, expected output ([u'echo', '-n', 1], '1'), ([u'echo', '-n', u'Köln'], 'Köln'), ] for cmd, x in data: r = run_command(cmd) assert r == x with pytest.raises(subprocess.CalledProcessError): run_command(['/usr/bin/false'])
def test_run_command(): """Run command.""" data = [ # command, expected output (["echo", "-n", 1], "1"), (["echo", "-n", "Köln"], "Köln"), ] for cmd, x in data: r = run_command(cmd) assert r == x with pytest.raises(subprocess.CalledProcessError): run_command(["/usr/bin/false"])
def sign_in(args): op = args[0] subdomain = args[2] password = args[3] if not password: print('Sign in failed due to empty password') return session_key = None return_code = 0 try: prompt = Popen(['echo', password], stdout=PIPE) session_key = run_command([op, 'signin', subdomain, '--output', 'raw'], stdin=prompt.stdout) prompt.wait() session_key = session_key.rstrip() except CalledProcessError as e: return_code = e.returncode if return_code is 0 and session_key is not None: # Store 1Password session key wf.store_data('session_key', session_key) if wf.stored_data('session_key') is None: print('Signed in, but failed to store session key') return print('Signed in') return if return_code is 145: print('Sign in failed due to incorrect password') return print('Sign in failed due to unknown error')
def main(wf): items_raw = wf.cached_data('items', data_func=None, max_age=30) # Get cached data if stale if items_raw is not None: items = json.loads(items_raw) push(wf, items) return wf.send_feedback() # Get cached 1Password session key session_key = wf.stored_data('session_key') if session_key is None: it = wf.add_item( title='Vault authentication has expired or is not valid', subtitle='Run \'Sign in\' Vault command in Alfred', arg='op signin', valid=True) it.setvar('authenticated', '0') return wf.send_feedback() args = wf.args op = args[0] jq = args[1] # Issue bash command to request list of items from 1Password return_code = 0 try: command_output = Popen([op, 'list', 'items', '--session', session_key], stdout=PIPE) items_raw = run_command([jq, '-a'], stdin=command_output.stdout) command_output.wait() except CalledProcessError as e: return_code = e.returncode # Error can occur when the user does not have any vault items if items_raw is None: wf.add_item( title='No items found in vault', valid=False, ) return wf.send_feedback() try: items = json.loads(items_raw) except ValueError as e: # Error can occur when authentication has expired it = wf.add_item( title='Vault authentication has expired or is not valid', subtitle='Run \'Sign in\' Vault command in Alfred', arg='op signin', valid=True) it.setvar('authenticated', '0') return wf.send_feedback() push(wf, items) wf.send_feedback() wf.cache_data('items', items_raw)
def _fetch_connections(self): """Get configurations from VPN app.""" connections = [] with timed('fetched Viscosity VPN connections'): cmd = self.program + ['list'] data = json.loads(run_command(cmd)) for t in data.items(): connections.append(VPN(*t)) return connections
def sign_out(args): op = args[0] session_key = wf.stored_data('session_key') if session_key is None: print('Already signed out') return # Destroy authentication with 1Password return_code = 0 try: run_command([op, 'signout', '--session={}'.format(session_key)]) except CalledProcessError as e: return_code = e.returncode if return_code is 0: wf.store_data('session_key', None) wf.cache_data('items', None) if wf.stored_data('session_key') is not None: print('Signed out, but failed to clear session key') return print('Signed out') return if return_code is 1: wf.store_data('session_key', None) wf.cache_data('items', None) if wf.stored_data('session_key') is not None: print( 'Signed out due to expired session, but failed to clear session key' ) return print('Signed out due to expired session') return print('Sign out failed due to unknown error') log.debug(return_code)
def _fetch_connections(self): """Get configurations from VPN app.""" connections = [] with timed('fetched Tunnelblick VPN connections'): cmd = self.program + ['list'] output = wf.decode(run_command(cmd)).strip() for line in output.split('\n'): active = True if line[0] == '1' else False name = line[2:] connections.append(VPN(name, active)) return connections
def _fetch_connections(self): """Get configurations from VPN app.""" connections = [] with timed('fetched builtin VPN connections'): cmd = self.program + ['list'] output = wf.decode(run_command(cmd)).strip() for idx, line in enumerate(output.split('\n')): if idx == 0: continue active = True if line.find("(Connected)") != -1 else False name = re.findall('"(.+)"', line)[0] connections.append(VPN(name, active)) return connections
def get_locations(): """Return list of available network locations.""" locations = [] cmd = ['/usr/sbin/scselect'] output = decode(run_command(cmd)) for line in output.split('\n'): m = match(line) if not m: continue state, id_, name = [s.strip() for s in m.groups()] state = True if state else False loc = Location(name, id_, state) log.debug('%r', loc) locations.append(loc) return locations
def main(wf): # Get cached 1Password session key session_key = wf.stored_data('session_key') if session_key is None: v.arg = 'Vault authentication has expired or is not valid' return args = wf.args op = args[0] jq = args[1] uuid = args[2] action = args[3] # Issue bash command to request item info from 1Password item_raw = None return_code = 0 try: command_output = Popen([op, 'get', 'item', uuid, '--session', session_key], stdout=PIPE) item_raw = run_command([jq, '-a'], stdin=command_output.stdout) command_output.wait() except CalledProcessError as e: return_code = e.returncode # Error can occur when authentication is not valid if item_raw is None: v.arg = 'Vault authentication has expired or is not valid' return item = json.loads(item_raw) item_fields = item['details']['fields'] item_field_value = None for item_field in item_fields: if item_field['name'] == action: item_field_value = item_field['value'] break # Error can occur when the desired field does not exist if not item_field_value or item_field_value is None: v.arg = 'Failed to obtain {} for this item'.format(action) return v.arg = 'Sent {} to active window and restored clipboard'.format(action) v['value']=item_field_value print(v)
def do_set_location(name): """Change to location ``name``.""" run_command(['/usr/sbin/scselect', name]) print(name.encode('utf-8'), end='') wf.clear_session_cache()
def disconnect_all(self): """Close all active VPNs.""" cmd = self.program + ['disconnect-all'] run_command(cmd)
def main(wf): # build argument parser to parse script args and collect their # values parser = argparse.ArgumentParser() # add an optional (nargs='?') --setkey argument and save its # value to 'apikey' (dest). This will be called from a separate "Run Script" # action with the API key parser.add_argument('--setkey', dest='apikey', nargs='?', default=None) parser.add_argument('--seturl', dest='apiurl', nargs='?', default=None) parser.add_argument('query', nargs='?', default=None) # parse the script's arguments args = parser.parse_args(wf.args) #################################################################### # Save the provided API key or URL #################################################################### # decide what to do based on arguments if args.apikey: # Script was passed an API key log.info("Setting API Key") wf.save_password('gitea_api_key', args.apikey) return 0 # 0 means script exited cleanly #################################################################### # Check that we have an API key saved #################################################################### try: wf.get_password('gitea_api_key') except PasswordNotFound: # API key has not yet been set wf.add_item('No API key set', 'Please use `tea set key` to set your Gitea API key.', valid=False, icon=ICON_ERROR) wf.send_feedback() return 0 #################################################################### # Check for the URL #################################################################### log.info(args.apiurl) # if user passed a new URL if args.apiurl: wf.settings['base_url'] = args.apiurl wf.settings['api_url'] = args.apiurl + "/api/v1/repos/search" # if not yet set, fall back to try.gitea.io elif not wf.settings.get('base_url'): wf.settings['base_url'] = 'https://try.gitea.io' wf.settings['api_url'] = 'https://try.gitea.io/api/v1/repos/search' return 0 log.debug( "Setting API URL to {url}".format(url=wf.settings.get('api_url'))) #################################################################### # View/filter gitea Projects #################################################################### query = args.query projects_gitea = wf.cached_data('projects_gitea', None, max_age=0) # log.debug('XXX %s', projects_gitea) if wf.update_available: # Add a notification to top of Script Filter results wf.add_item('New version available', 'Action this item to install the update', autocomplete='workflow:update', icon=ICON_INFO) # Notify the user if the cache is being updated if is_running('update') and not projects_gitea: log.info("Updating project list via gitea..") wf.rerun = 0.5 wf.add_item( 'Updating project list via gitea...', subtitle= u'This can take some time if you have a large number of projects.', valid=False, icon=ICON_INFO) # Start update script if cached data is too old (or doesn't exist) if not wf.cached_data_fresh('projects_gitea', max_age=1) and not is_running('update'): cmd = ['/usr/bin/python3', wf.workflowfile('update.py')] # run_in_background('update', cmd) # foreground for debugging run_command(cmd) wf.rerun = 0.5 # If script was passed a query, use it to filter projects if query and projects_gitea: projects_gitea = wf.filter(query, projects_gitea, key=search_for_project, min_score=20) if not projects_gitea: # we have no data to show, so show a warning and stop wf.add_item('No projects found', icon=ICON_WARNING) wf.send_feedback() return 0 # log.debug('%s', projects_gitea) # Create thumbnails from repo avatars - slow! # thumbs = Thumbs(wf.datafile('thumbs')) # Loop through the returned posts and add an item for each to # the list of results for Alfred for project in projects_gitea: # icon = wf.add_item( title=project['full_name'], subtitle=project['description'], arg=project['html_url'], valid=True, # Create thumbnails from repo avatars - slow! # icon=thumbs.thumbnail(requests.get(project['owner']['avatar_url']).url), icon=wf.workflowfile('gitea-transparent.png'), largetext=project['full_name'], quicklookurl=project['html_url'], copytext=project['html_url'], uid=project['id']) # Send the results to Alfred as XML wf.send_feedback()