def ns_all(): """ Return all namespaces """ # We do this outside the blueprint to support the case of an empty # public_id. However, this means the before_request isn't run, so we need # to make our own session with session_scope() as db_session: parser = reqparse.RequestParser(argument_class=ValidatableArgument) parser.add_argument('limit', default=DEFAULT_LIMIT, type=limit, location='args') parser.add_argument('offset', default=0, type=int, location='args') parser.add_argument('email_address', type=bounded_str, location='args') args = strict_parse_args(parser, request.args) query = db_session.query(Namespace) if args['email_address']: query = query.join(Account) query = query.filter_by(email_address=args['email_address']) query = query.limit(args['limit']) if args['offset']: query = query.offset(args['offset']) namespaces = query.all() encoder = APIEncoder(legacy_nsid=request.path.startswith('/n')) return encoder.jsonify(namespaces)
def modify_account(namespace_public_id): """ Modify an existing account This stops syncing an account until it is explicitly resumed. """ data = request.get_json(force=True) with global_session_scope() as db_session: namespace = (db_session.query(Namespace).filter( Namespace.public_id == namespace_public_id).one()) account = namespace.account if isinstance(account, GenericAccount): auth_handler = GenericAuthHandler() account_data = _get_account_data_for_generic_account(data) elif isinstance(account, GmailAccount): auth_handler = GoogleAuthHandler() account_data = _get_account_data_for_google_account(data) elif isinstance(account, OutlookAccount): auth_handler = MicrosoftAuthHandler() account_data = _get_account_data_for_microsoft_account(data) else: raise ValueError("Account type not supported.") account = auth_handler.update_account(account, account_data) db_session.add(account) db_session.commit() encoder = APIEncoder() return encoder.jsonify(account.namespace)
def message_read_api(public_id): g.parser.add_argument('view', type=view, location='args') args = strict_parse_args(g.parser, request.args) encoder = APIEncoder(g.namespace.public_id, args['view'] == 'expanded') try: valid_public_id(public_id) message = g.db_session.query(Message).filter( Message.public_id == public_id, Message.namespace_id == g.namespace.id).one() except NoResultFound: raise NotFoundError("Couldn't find message {0} ".format(public_id)) if request.headers.get('Accept', None) == 'message/rfc822': if message.full_body is not None: return Response(message.full_body.data, mimetype='message/rfc822') else: g.log.error("Message without full_body attribute: id='{0}'" .format(message.id)) raise NotFoundError( "Couldn't find raw contents for message `{0}` " .format(public_id)) return encoder.jsonify(message)
def ns_all(): """ Return all namespaces """ # We do this outside the blueprint to support the case of an empty # public_id. However, this means the before_request isn't run, so we need # to make our own session with global_session_scope() as db_session: parser = reqparse.RequestParser(argument_class=ValidatableArgument) parser.add_argument('limit', default=DEFAULT_LIMIT, type=limit, location='args') parser.add_argument('offset', default=0, type=int, location='args') parser.add_argument('email_address', type=bounded_str, location='args') args = strict_parse_args(parser, request.args) query = db_session.query(Namespace) if args['email_address']: query = query.join(Account) query = query.filter_by(email_address=args['email_address']) query = query.limit(args['limit']) if args['offset']: query = query.offset(args['offset']) namespaces = query.all() encoder = APIEncoder(legacy_nsid=request.path.startswith('/n')) return encoder.jsonify(namespaces)
def ns_all(): """ Return all namespaces """ # We do this outside the blueprint to support the case of an empty # public_id. However, this means the before_request isn't run, so we need # to make our own session with session_scope() as db_session: namespaces = db_session.query(Namespace).all() encoder = APIEncoder() return encoder.jsonify(namespaces)
def message_query_api(): g.parser.add_argument('subject', type=bounded_str, location='args') g.parser.add_argument('to', type=bounded_str, location='args') g.parser.add_argument('from', type=bounded_str, location='args') g.parser.add_argument('cc', type=bounded_str, location='args') g.parser.add_argument('bcc', type=bounded_str, location='args') g.parser.add_argument('any_email', type=bounded_str, location='args') g.parser.add_argument('started_before', type=timestamp, location='args') g.parser.add_argument('started_after', type=timestamp, location='args') g.parser.add_argument('last_message_before', type=timestamp, location='args') g.parser.add_argument('last_message_after', type=timestamp, location='args') g.parser.add_argument('filename', type=bounded_str, location='args') g.parser.add_argument('in', type=bounded_str, location='args') g.parser.add_argument('thread_id', type=valid_public_id, location='args') g.parser.add_argument('unread', type=strict_bool, location='args') g.parser.add_argument('starred', type=strict_bool, location='args') g.parser.add_argument('view', type=view, location='args') # For backwards-compatibility -- remove after deprecating tags API. g.parser.add_argument('tag', type=bounded_str, location='args') args = strict_parse_args(g.parser, request.args) # For backwards-compatibility -- remove after deprecating tags API. in_ = args['in'] or args['tag'] messages = filtering.messages_or_drafts( namespace_id=g.namespace.id, drafts=False, subject=args['subject'], thread_public_id=args['thread_id'], to_addr=args['to'], from_addr=args['from'], cc_addr=args['cc'], bcc_addr=args['bcc'], any_email=args['any_email'], started_before=args['started_before'], started_after=args['started_after'], last_message_before=args['last_message_before'], last_message_after=args['last_message_after'], filename=args['filename'], in_=in_, unread=args['unread'], starred=args['starred'], limit=args['limit'], offset=args['offset'], view=args['view'], db_session=g.db_session) # Use a new encoder object with the expand parameter set. encoder = APIEncoder(g.namespace.public_id, args['view'] == 'expanded') return encoder.jsonify(messages)
def thread_api(public_id): g.parser.add_argument('view', type=view, location='args') args = strict_parse_args(g.parser, request.args) # Use a new encoder object with the expand parameter set. encoder = APIEncoder(g.namespace.public_id, args['view'] == 'expanded') try: valid_public_id(public_id) thread = g.db_session.query(Thread).filter( Thread.public_id == public_id, Thread.namespace_id == g.namespace.id).one() return encoder.jsonify(thread) except NoResultFound: raise NotFoundError("Couldn't find thread `{0}`".format(public_id))
def delete_account(namespace_public_id): """ Mark an existing account for deletion. """ try: with global_session_scope() as db_session: namespace = (db_session.query(Namespace).filter( Namespace.public_id == namespace_public_id).one()) account = namespace.account account.mark_for_deletion() db_session.commit() except NoResultFound: raise NotFoundError( "Couldn't find account `{0}` ".format(namespace_public_id)) encoder = APIEncoder() return encoder.jsonify({})
def thread_query_api(): g.parser.add_argument('subject', type=bounded_str, location='args') g.parser.add_argument('to', type=bounded_str, location='args') g.parser.add_argument('from', type=bounded_str, location='args') g.parser.add_argument('cc', type=bounded_str, location='args') g.parser.add_argument('bcc', type=bounded_str, location='args') g.parser.add_argument('any_email', type=bounded_str, location='args') g.parser.add_argument('started_before', type=timestamp, location='args') g.parser.add_argument('started_after', type=timestamp, location='args') g.parser.add_argument('last_message_before', type=timestamp, location='args') g.parser.add_argument('last_message_after', type=timestamp, location='args') g.parser.add_argument('filename', type=bounded_str, location='args') g.parser.add_argument('thread_id', type=valid_public_id, location='args') g.parser.add_argument('tag', type=bounded_str, location='args') g.parser.add_argument('view', type=view, location='args') args = strict_parse_args(g.parser, request.args) threads = filtering.threads( namespace_id=g.namespace.id, subject=args['subject'], thread_public_id=args['thread_id'], to_addr=args['to'], from_addr=args['from'], cc_addr=args['cc'], bcc_addr=args['bcc'], any_email=args['any_email'], started_before=args['started_before'], started_after=args['started_after'], last_message_before=args['last_message_before'], last_message_after=args['last_message_after'], filename=args['filename'], tag=args['tag'], limit=args['limit'], offset=args['offset'], view=args['view'], db_session=g.db_session) # Use a new encoder object with the expand parameter set. encoder = APIEncoder(g.namespace.public_id, args['view'] == 'expanded') return encoder.jsonify(threads)
def confim_oauth_user(): response = {} encoder = APIEncoder() data = request.get_json(force=True) email_address = data.get('email_address') token = data.get('token') target = data.get('target', 0) if not email_address: response['error'] = 'Missing key - "email_address"!' return encoder.jsonify(response) if not token: response['error'] = 'Missing key - "token"!' return encoder.jsonify(response) shard_id = target << 48 with session_scope(shard_id) as db_session: account = db_session.query(Account).filter_by( email_address=email_address).first() if account is None: response['error'] = 'Don\'t have this account!' return encoder.jsonify(response) auth_info = {} provider = provider_from_address(email_address) auth_info['provider'] = provider auth_handler = handler_from_provider(provider) try: auth_response = auth_handler._get_authenticated_user(token) auth_response['contacts'] = True auth_response['events'] = True auth_info.update(auth_response) except OAuthError: response['error'] = "Invalid authorization code, try again..." return encoder.jsonify(response) account = auth_handler.update_account(account, auth_info) try: if auth_handler.verify_account(account): db_session.add(account) db_session.commit() response['data'] = 'OK. Authenticated account for {}'.format( email_address) except NotSupportedError as e: response['error'] = str(e) return encoder.jsonify(response) return encoder.jsonify(response)
def create_account(): """ Create a new account """ data = request.get_json(force=True) if data["type"] == "generic": auth_handler = GenericAuthHandler() account_data = _get_account_data_for_generic_account(data) elif data["type"] == "gmail": auth_handler = GoogleAuthHandler() account_data = _get_account_data_for_google_account(data) elif data["type"] == "microsoft": auth_handler = MicrosoftAuthHandler() account_data = _get_account_data_for_microsoft_account(data) else: raise ValueError("Account type not supported.") with global_session_scope() as db_session: account = auth_handler.create_account(account_data) db_session.add(account) db_session.commit() encoder = APIEncoder() return encoder.jsonify(account.namespace)
def add_new_user(): response = {} encoder = APIEncoder() data = request.get_json(force=True) email_address = data.get('email_address') password = data.get('password') auth_details = data.get('auth_details') reauth = data.get('reauth') target = data.get('target', 0) if not email_address: response['error'] = 'Missing key - "email_address"!' return encoder.jsonify(response) shard_id = target << 48 with session_scope(shard_id) as db_session: account = db_session.query(Account).filter_by( email_address=email_address).first() if account is not None and not reauth: response['error'] = 'Already have this account!' return encoder.jsonify(response) auth_info = {} provider = provider_from_address(email_address) if 'gmail' in provider: auth_handler = handler_from_provider(provider) response['oauth_url'] = auth_handler.get_oauth_url(email_address) response['links'] = {'confirm_url': request.url + '/confirm_oauth'} namespace = Namespace() account = GmailAccount(namespace=namespace) account.sync_should_run = False account.refresh_token = '_placeholder_' account.email_address = email_address else: if not password: response['error'] = 'Missing key - "password"!' return encoder.jsonify(response) auth_info['email'] = email_address auth_info['password'] = password if provider != 'unknown': auth_handler = handler_from_provider(provider) auth_info['provider'] = provider try: if reauth: account = auth_handler.update_account( account, auth_info) else: account = auth_handler.create_account( email_address, auth_info) except Exception as e: response['error'] = e.msg else: auth_info['provider'] = 'custom' auth_handler = handler_from_provider('custom') if not auth_details: auth_info.update( try_fill_config_data(email_address, password)) else: auth_info.update(auth_details) try: if reauth: account = auth_handler.update_account( account, auth_info) else: account = auth_handler.create_account( email_address, auth_info) except Exception as e: response['error'] = str(e) try: auth_handler.verify_account(account) response['data'] = 'OK. Authenticated account for {}'.format( email_address) except Exception as e: response['error'] = str(e) db_session.add(account) db_session.commit() return encoder.jsonify(response)