def is_valid_token(token): """Check that the user has a valid token.""" # Set auth object auth = Auth(token) try: # Make request result = auth.test() except Error as err: # Check for auth errors stf.report_event(str(err), { 'token': token }) return False # Check for further errors if not result.successful: stf.report_event('token_invalid', { 'token': token, 'result': result.__dict__ }) return False # Return successful return True
def get_token(code, scope="user"): """Request a token from the Slack API.""" # Set OAuth access object oauth = OAuth() # Setup return URL return_url = "{0}_url".format(scope) try: # Attempt to make request result = oauth.access( client_id=PROJECT_INFO["client_id"], client_secret=PROJECT_INFO["client_secret"], redirect_uri=PROJECT_INFO[return_url], code=code, ) except Error as err: report_event("oauth_error", {"code": code, "return_url": return_url, "error": str(err)}) abort(400) if not result.successful: report_event("oauth_unsuccessful", {"code": code, "return_url": return_url, "result": result.__dict__}) abort(400) # Return token return result.body["access_token"]
def send_flip(token, table, args): """Post the flip as the authenticated user in Slack.""" # Set up chat object chat = Chat(token) try: # Attempt to post message chat.post_message( args['channel_id'], table, username=args['user_id'], as_user=True ) except Error as err: stf.report_event(str(err), { 'token': token, 'table': table, 'args': args }) # Report if we got any errors return '{0} encountered an error: {1}'.format( stf.PROJECT_INFO['name_full'], str(err) ) # Return successful return
def store_user(token, info): """Store a validated user in the database.""" # Check if user exists user = DB.session.query(Users).filter(Users.id == info['user_id']).filter( Users.team == info['team_id']).first() if user is None: # Create new user new_user = Users(info['user_id']) new_user.team = info['team_id'] new_user.token = token # Store new user report_event('user_added', {'token': token, 'info': info}) DB.session.add(new_user) else: # Update user token report_event('user_updated', {'token': token, 'info': info}) user.token = token # Update DB DB.session.commit() return
def validate_return(args, scope="user"): """Wrapper function for data validation functions.""" # Make sure we have args if not args["state"] or not args["code"]: report_event("missing_args", args) abort(400) # Validate state validate_state(args["state"]) # Get access token token = get_token(args["code"], scope) # Validate token and get info token_info = validate_token(token) # Set up storage methods store_methods = {"user": store_user, "team": store_team} # Store token data store_methods[scope](token, token_info) # Set success url redirect_url = "{0}?success=1".format(PROJECT_INFO["base_url"]) # Return successful return redirect_url
def validate_return(args, scope='user'): """Wrapper function for data validation functions.""" # Make sure we have args if not args['state'] or not args['code']: report_event('missing_args', args) abort(400) # Validate state validate_state(args['state']) # Get access token token = get_token(args['code'], scope) # Validate token and get info token_info = validate_token(token) # Set up storage methods store_methods = {'user': store_user, 'team': store_team} # Store token data store_methods[scope](token, token_info) # Set success url redirect_url = '{0}?success=1'.format(PROJECT_INFO['base_url']) # Return successful return redirect_url
def send_flip(token, table, args): """Post the flip as the authenticated user in Slack.""" # Set up chat object chat = Chat(token) try: # Attempt to post message chat.post_message(args['channel_id'], table, username=args['user_id'], as_user=True) except Error as err: stf.report_event(str(err), { 'token': token, 'table': table, 'args': args }) # Report if we got any errors return '{app} encountered an error: {error}'.format( app=stf.PROJECT_INFO['name_full'], error=str(err)) # Return without errors return None
def get_token(code, scope='user'): """Request a token from the Slack API.""" # Set OAuth access object oauth = OAuth() # Setup return URL return_url = '{0}_url'.format(scope) try: # Attempt to make request result = oauth.access(client_id=PROJECT_INFO['client_id'], client_secret=PROJECT_INFO['client_secret'], redirect_uri=PROJECT_INFO[return_url], code=code) except Error as err: report_event('oauth_error', { 'code': code, 'return_url': return_url, 'error': str(err) }) abort(400) if not result.successful: report_event('oauth_unsuccessful', { 'code': code, 'return_url': return_url, 'result': result.__dict__ }) abort(400) # Return token return result.body['access_token']
def hmmm(): report_event('post_request', request.form.to_dict()) if PROJECT_INFO['debug']: print("************", file=stderr) print(request, file=stderr) print("************", file=stderr) return flipper.flip(request.form.to_dict())
def home(): """Render app homepage template.""" if request.method == 'POST': report_event('post_request', request.form.to_dict()) return flipper.flip(request.form.to_dict()) else: return render_template('index.html', project=PROJECT_INFO, allowed_types=ALLOWED_TYPES, allowed_commands=ALLOWED_COMMANDS)
def home(): """Render app homepage template.""" if request.method == 'POST': report_event('post_request', request.form.to_dict()) return flipper.flip(request.form.to_dict()) else: return render_template( 'index.html', project=PROJECT_INFO, allowed_types=ALLOWED_TYPES, allowed_commands=ALLOWED_COMMANDS )
def __call__(self, parser, namespace, values, option_string=None): """Validate flip arguments and stores them to namespace.""" flip_type = values[0].lower() flip_word = None # Check for help if flip_type in ['help', 'list', 'version']: parser.print_help(flip_type) return # Check that the type is valid if (flip_type not in stf.ALLOWED_TYPES and flip_type not in stf.WORD_TYPES and flip_type not in stf.RESTORE_TYPES): stf.report_event('flip_invalid', { 'flip': flip_type }) parser.error( 'Flip type "{0}" is not known'.format( flip_type.encode('utf-8') ) ) if flip_type in stf.WORD_TYPES or flip_type in stf.RESTORE_TYPES: if len(values) >= 2: # Set word value flip_word = ' '.join(values[1:len(values)]) else: # Check for flip that requires words if flip_type == 'word': stf.report_event('flip_missing_word', { 'flip': flip_type }) parser.error( 'Flip type "{0}" requires words to flip'.format( flip_type.encode('utf-8') ) ) # Set values setattr(namespace, 'flip_type', flip_type) setattr(namespace, 'flip_word', flip_word) return
def validate_token(token): """Validate token and retrieves info from Slack API.""" # Set auth object auth = Auth(token) try: # Make request result = auth.test() except Error as err: report_event(str(err), {"token": token}) abort(400) # Check for errors if not result.successful: report_event("token_invalid", {"token": token, "result": result.__dict__}) abort(400) # Return user info return result.body
def store_team(token, info): """Store a validated team in the database.""" # Check if team exists team = Teams.query.get(info['team_id']) if team is None: # Create new team new_team = Teams(team_id=info['team_id'], token=token) # Store new team report_event('team_added', {'token': token, 'info': info}) DB.session.add(new_team) else: # Update team token report_event('team_updated', {'token': token, 'info': info}) team.token = token # Update DB DB.session.commit()
def validate_state(state): """Validate state token returned by authentication.""" try: # Attempt to decode state state_token = GENERATOR.loads( state, max_age=timedelta(minutes=60).total_seconds()) except SignatureExpired: # Token has expired report_event('token_expired', {'state': state}) abort(400) except BadSignature: # Token is not authorized report_event('token_not_authorized', {'state': state}) abort(401) if state_token != PROJECT_INFO['client_id']: # Token is not authorized report_event('token_not_valid', { 'state': state, 'state_token': state_token }) abort(401) # Return success return
def flip(args): """Wrapper function for flip functions.""" # Reset global error traker global ERRORS ERRORS = [] # Make sure this is a valid slash command if args['command'] not in stf.ALLOWED_COMMANDS: stf.report_event('command_not_allowed', args) return '"{0}" is not an allowed command'.format(args['command']) else: # Set global command value to access later global COMMAND COMMAND = args['command'] # Check to see if user has authenticated with the app token = check_user(args) # If the user or token is not valid, let them know if token is None or not is_valid_token(token): stf.report_event('auth_error', {'args': args, 'token': token}) return AUTH_ERROR # If there's no input, use the default flip if not args['text']: flip_type = 'classic' flip_word = None else: # Set up text args for parser text_args = args['text'].split() # Get parser parser = get_parser() # Parse args result = parser.parse_args(text_args) # Report any errors from parser if len(ERRORS) > 0: stf.report_event('parser_errors', {'errors': ERRORS}) return ERRORS[0] # Set values flip_type = result.flip_type flip_word = result.flip_word # Get requested flip table = do_flip(flip_type, flip_word) # Post flip as user err = send_flip(token, table, args) # If there were problems posting, report it if err is not None: return err # Return successful return ('', 204)
def store_team(token, info): """Store a validated team in the database.""" # Check if team exists team = Teams.query.get(info["team_id"]) if team is None: # Create new team new_team = Teams(info["team_id"]) new_team.token = token # Store new team report_event("team_added", {"token": token, "info": info}) DB.session.add(new_team) else: # Update team token report_event("team_updated", {"token": token, "info": info}) team.token = token # Update DB DB.session.commit() return
def validate_token(token): """Validate token and retrieves info from Slack API.""" # Set auth object auth = Auth(token) try: # Make request result = auth.test() except Error as err: report_event(str(err), {'token': token}) abort(400) # Check for errors if not result.successful: report_event('token_invalid', { 'token': token, 'result': result.__dict__ }) abort(400) # Return user info return result.body
def __call__(self, parser, namespace, values, option_string=None): """Validate flip arguments and stores them to namespace.""" flip_type = values[0].lower() flip_word = None # Check for help if flip_type in ['help', 'list', 'version']: parser.print_help(flip_type) return # Check that the type is valid if (flip_type not in stf.ALLOWED_TYPES and flip_type not in stf.WORD_TYPES and flip_type not in stf.RESTORE_TYPES): stf.report_event('flip_invalid', {'flip': flip_type}) parser.error( 'Flip type "{type}" is not known'.format(type=flip_type)) if flip_type in stf.WORD_TYPES or flip_type in stf.RESTORE_TYPES: if len(values) >= 2: # Set word value flip_word = ' '.join(values[1:len(values)]) else: # Check for flip that requires words if flip_type == 'word': stf.report_event('flip_missing_word', {'flip': flip_type}) parser.error( 'Flip type "{type}" requires words to flip'.format( type=flip_type)) # Set values setattr(namespace, 'flip_type', flip_type) setattr(namespace, 'flip_word', flip_word) return
def store_user(token, info): """Store a validated user in the database.""" # Check if user exists user = DB.session.query(Users).filter(Users.id == info["user_id"]).filter(Users.team == info["team_id"]).first() if user is None: # Create new user new_user = Users(info["user_id"]) new_user.team = info["team_id"] new_user.token = token # Store new user report_event("user_added", {"token": token, "info": info}) DB.session.add(new_user) else: # Update user token report_event("user_updated", {"token": token, "info": info}) user.token = token # Update DB DB.session.commit() return
def is_valid_token(token): """Check that the user has a valid token.""" # Set auth object auth = Auth(token) try: # Make request result = auth.test() except Error as err: # Check for auth errors stf.report_event(str(err), {'token': token}) return False # Check for further errors if not result.successful: stf.report_event('token_invalid', { 'token': token, 'result': result.__dict__ }) return False # Return successful return True
def validate_state(state): """Validate state token returned by authentication.""" try: # Attempt to decode state state_token = GENERATOR.loads(state, max_age=timedelta(minutes=60).total_seconds()) except SignatureExpired: # Token has expired report_event("token_expired", {"state": state}) abort(400) except BadSignature: # Token is not authorized report_event("token_not_authorized", {"state": state}) abort(401) if state_token != PROJECT_INFO["client_id"]: # Token is not authorized report_event("token_not_valid", {"state": state, "state_token": state_token}) abort(401) # Return success return
def flip(args): """Wrapper function for flip functions.""" # Reset global error traker global ERRORS ERRORS = [] # Make sure this is a valid slash command if args['command'] not in stf.ALLOWED_COMMANDS: stf.report_event('command_not_allowed', args) return '"{0}" is not an allowed command'.format(args['command']) else: # Set global command value to access later global COMMAND COMMAND = args['command'] # Check to see if user has authenticated with the app token = check_user(args) # If the user or token is not valid, let them know if token is None or not is_valid_token(token): stf.report_event('auth_error', { 'args': args, 'token': token }) return AUTH_ERROR # If there's no input, use the default flip if not args['text']: flip_type = 'classic' flip_word = None else: # Set up text args for parser text_args = args['text'].split() # Get parser parser = get_parser() # Parse args result = parser.parse_args(text_args) # Report any errors from parser if len(ERRORS) > 0: stf.report_event('parser_errors', { 'errors': ERRORS }) return ERRORS[0] # Set values flip_type = result.flip_type flip_word = result.flip_word # Get requested flip table = do_flip(flip_type, flip_word) # Post flip as user err = send_flip(token, table, args) # If there were problems posting, report it if err is not None: return err # Return successful return ('', 204)