async def post_paste(request): # Creates a new paste. body = await request.json() _verify_body(body) body['title'] = body['title'] or 'Untitled' date = datetime.now() user_id, _ = _get_claims(request.cookies, request.app['jwt_key'], request.app['jwt_algorithm']) if body['exposure'] == 'Private' and user_id is None: raise web.HTTPBadRequest( 'Cannot create a private paste while not logged in') async with request.app['db_engine'].acquire() as conn: async with transaction_context(conn) as tc_conn: await tc_conn.execute(pastes_table.insert().values(date=date, user_id=user_id, **body)) new_id = await tc_conn.execute('SELECT LAST_INSERT_ID();') new_id = await new_id.scalar() return web.json_response({'id': new_id})
async def delete_paste(request): paste_id = request.match_info['id'] async with request.app['db_engine'].acquire() as conn: await _should_authorize(conn, paste_id, request.cookies, request.app['jwt_key'], request.app['jwt_algorithm']) async with transaction_context(conn) as tc_conn: await tc_conn.execute( pastes_table.delete().where(pastes_table.c.id == paste_id)) return web.HTTPNoContent()
def test_select(): with transaction_context() as session: p1 = session.query(Parent)\ .options(joinedload(Parent.children))\ .filter(Parent.name == "p1")\ .one_or_none() print(p1.name) for child in p1.children: print(child.name)
def insert_test_data(): with transaction_context() as session: p1 = Parent() p1.name = "p1" c1 = Child() c1.name = "c1" c2 = Child() c2.name = "c2" p1.childs = [c1, c2] session.add(p1)
async def put_paste(request): # Updates an existing paste. # Only a logged in user can update their pastes. body = await request.json() _verify_body(body) paste_id = request.match_info['id'] async with request.app['db_engine'].acquire() as conn: await _should_authorize(conn, paste_id, request.cookies, request.app['jwt_key'], request.app['jwt_algorithm']) async with transaction_context(conn) as tc_conn: await tc_conn.execute(pastes_table.update().where( pastes_table.c.id == paste_id).values(**body)) return web.HTTPNoContent()
async def twitter_login(request): # Implements the first step of login with Twitter. twitter_api_key = request.app['twitter_api_key'] twitter_api_secret_key = request.app['twitter_api_secret_key'] twitter_oauth_callback = request.app['twitter_oauth_callback'] request_token_endpoint = request.app['request_token_endpoint'] authenticate_endpoint = request.app['authenticate_endpoint'] client = oauthlib.oauth1.Client(twitter_api_key, client_secret=twitter_api_secret_key, callback_uri=twitter_oauth_callback) uri, headers, _ = client.sign(request_token_endpoint, http_method='POST') session = request.app['client_session'] # Fetch an unauthorized request token. async with session.post(uri, headers=headers) as response: if response.status != 200: raise web.HTTPInternalServerError() body = await response.text() # Parse oauth_token, oauth_token_secret, oauth_callback_confirmed. body = dict([pair.split('=') for pair in body.split('&')]) if body.get('oauth_callback_confirmed') != 'true': raise web.HTTPInternalServerError() oauth_token = body['oauth_token'] oauth_token_secret = body['oauth_token_secret'] # Store oauth_token and oauth_token_secret so they can be used at the next stage of the sign in process. async with request.app['db_engine'].acquire() as conn: result = await conn.execute(login_sessions_table.select().where( login_sessions_table.c.oauth_token == oauth_token)) login_session = await result.first() if login_session is None: async with transaction_context(conn) as tc_conn: await tc_conn.execute(login_sessions_table.insert().values( oauth_token=oauth_token, oauth_token_secret=oauth_token_secret)) # Redirect the user to Twitter so they can authenticate themselves and authorize pastecan. raise web.HTTPFound( URL(authenticate_endpoint) % {'oauth_token': oauth_token})
async def token(request): # Implements the third step of log in with Twitter. params = request.query params_oauth_token = params.get('oauth_token') oauth_verifier = params.get('oauth_verifier') oauth_token = None oauth_token_secret = None # Check if the token provided by the user is presnet in session data. async with request.app['db_engine'].acquire() as conn: result = await conn.execute(login_sessions_table.select().where( login_sessions_table.c.oauth_token == params_oauth_token)) session_data = await result.first() if session_data is None: raise web.HTTPBadRequest('Could not verify the OAuth token') session_data = { column: value for column, value in session_data.items() } oauth_token = session_data['oauth_token'] oauth_token_secret = session_data['oauth_token_secret'] # Clean up login session data. This should also be done periodically for example using a background task. # https://docs.aiohttp.org/en/stable/web_advanced.html#background-tasks await conn.execute(login_sessions_table.delete().where( login_sessions_table.c.oauth_token == params_oauth_token)) if oauth_token != params_oauth_token: raise web.HTTPBadRequest('Could not verify the Oauth token') twitter_api_key = request.app['twitter_api_key'] twitter_api_secret_key = request.app['twitter_api_secret_key'] access_token_endpoint = request.app['access_token_endpoint'] client = oauthlib.oauth1.Client(twitter_api_key, client_secret=twitter_api_secret_key, resource_owner_key=oauth_token, resource_owner_secret=oauth_token_secret) request_body = f'oauth_verifier={oauth_verifier}' headers = {'Content-Type': 'application/x-www-form-urlencoded'} uri, headers, request_body = client.sign(access_token_endpoint, http_method='POST', headers=headers, body=request_body) session = request.app['client_session'] # Fetch access token. async with session.post(uri, headers=headers, data=request_body) as response: if response.status != 200: raise web.HTTPInternalServerError( 'Could not receive an access token') body = await response.text() # Parse oauth_token, oauth_token_secret, user_id, screen_name. body = dict([pair.split('=') for pair in body.split('&')]) user_id_third_step = body['user_id'] # Determine identity of the user using GET account/verify_credentials. client = oauthlib.oauth1.Client( twitter_api_key, client_secret=twitter_api_secret_key, resource_owner_key=body['oauth_token'], resource_owner_secret=body['oauth_token_secret']) verify_credentials_endpoint = request.app['verify_credentials_endpoint'] uri, headers, _ = client.sign(verify_credentials_endpoint, http_method='GET') async with session.get(uri, headers=headers) as response: if response.status != 200: raise web.HTTPInternalServerError('Could not verify user identity') body = await response.json() user_id = body['id_str'] user_screen_name = body['screen_name'] if user_id != user_id_third_step: raise web.HTTPInternalServerError('User identity mismatch') # Store user data in the database if it is not already present. async with request.app['db_engine'].acquire() as conn: result = await conn.execute( users_table.select().where(users_table.c.user_id == user_id)) user = await result.first() if user is None: async with transaction_context(conn) as tc_conn: await tc_conn.execute(users_table.insert().values( user_id=user_id, screen_name=user_screen_name)) # Issue a JWT for the user. encoded = _create_token(user_id, user_screen_name, request.app['jwt_key'], request.app['jwt_algorithm']) response = web.HTTPFound('/') response.set_cookie(TOKEN_COOKIE, encoded, max_age=60 * 60 * 24, secure=True, samesite='Strict', httponly=True) # Should expire in 24h. response.set_cookie('screenName', user_screen_name, max_age=60 * 60 * 24, secure=True, samesite='Strict') return response
def test_delete_cascade(): with transaction_context() as session: session.query(Parent).filter(Parent.name == "p1").delete()