async def bank(request: HTTPConnection): login_form = LoginForm() transfer_form = TransferForm() current_user = request.cookies.get("username") return templates.TemplateResponse( "bank.j2", { "request": request, "login_form": login_form, "transfer_form": transfer_form, "login_url": request.url_for("bank_login"), "transfer_url": request.url_for("bank_transfer"), "current_user": current_user, "transactions": [] if current_user is None else transactions[current_user], }, )
async def auth_cb(request: HTTPConnection): token = await oauth.discord.authorize_access_token(request) resp = await oauth.discord.get(DISCORD_API_BASE + "/users/@me", token=token, auth=UNSET) user = resp.json() request.session["discord_id"] = int(user["id"]) request.session["discord_username"] = user["username"] return RedirectResponse(url="/")
async def authenticate( self, conn: HTTPConnection) -> Optional[Tuple[AuthCredentials, User]]: if 'token' in conn.cookies: token = json.loads(conn.cookies.get('token')) user = json.loads(conn.cookies.get('user')) expires_at = datetime.utcfromtimestamp(token['expires_at']) refresh_token = token['refresh_token'] now = datetime.now() # Check token expiration if expires_at > now: token, user = await self._refresh_access_token(refresh_token) self._update_auth_cookies(conn, token, user) self._add_data_to_session(conn, token, user) # Check user in database user_model = await self._check_user_in_db(user) # Store token and user in global context conn.scope['user'] = user conn.scope['token'] = token return AuthCredentials(['authenticated']), user_model return
async def validate_refresh_token(conn: HTTPConnection): """ Validate the refresh token """ user = conn.session.get("user", {}) if user.get("exp", 0) < time.time(): # User is expired, remove their session if user: del conn.session["user"] # The token is expired, try to refresh refresh_token = conn.session.get("refresh_token") if refresh_token: metadata = await oauth.storium.load_server_metadata() async with oauth.storium._get_oauth_client( # pylint:disable=protected-access **metadata ) as client: try: token = await client.refresh_token( metadata["token_endpoint"], refresh_token ) conn.session["refresh_token"] = token.get("refresh_token") # Refresh was successful, set user session user = await oauth.storium.parse_id_token(conn, token) conn.session["user"] = dict(user) except OAuthError as exc: # The refresh token has likely expired logger.error(exc)
async def authenticate( self, conn: HTTPConnection) -> Tuple[bool, Optional[User]]: """ Main function that AuthenticationMiddleware uses from this backend. Should return whether request is authenticated based on credentials and if it was, return also user instance. :param conn: HTTPConnection of the current request-response cycle :return: 2-tuple: is authenticated & user instance if exists """ authorization: str = conn.headers.get("Authorization") if not authorization: return False, None scheme, credentials = get_authorization_scheme_param(authorization) if not (authorization and scheme and credentials): raise AuthenticationError("Not authenticated") if scheme.lower() != "token": raise AuthenticationError("Invalid authentication credentials") token = await Token.get( key=credentials, is_active=True, expires={"$not": { "$lt": get_now() }}, ) if token is None: return False, None conn.scope["token"] = token user = await User.get(id=token.user_id) if user is None: return False, None return True, user
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: if scope["type"] not in ("http", "websocket"): # pragma: no cover await self.app(scope, receive, send) return connection = HTTPConnection(scope) initial_session_was_empty = True if self.session_cookie in connection.cookies: data = connection.cookies[self.session_cookie].encode("utf-8") try: jwt_payload = jwt.decode( data, str( self.jwt_secret.decode if self.jwt_secret.decode else self.jwt_secret.encode ), ) jwt_payload.validate_exp(time.time(), 0) scope["session"] = jwt_payload initial_session_was_empty = False except (BadSignatureError, ExpiredTokenError): scope["session"] = {} else: scope["session"] = {} async def send_wrapper(message: Message) -> None: if message["type"] == "http.response.start": if scope["session"]: if "exp" not in scope["session"]: scope["session"]["exp"] = int(time.time()) + self.max_age data = jwt.encode( self.jwt_header, scope["session"], str(self.jwt_secret.encode) ) headers = MutableHeaders(scope=message) header_value = "%s=%s; path=/; Max-Age=%d; %s" % ( self.session_cookie, data.decode("utf-8"), self.max_age, self.security_flags, ) if self.domain: # pragma: no cover header_value += f"; domain={self.domain}" headers.append("Set-Cookie", header_value) elif not initial_session_was_empty: # The session has been cleared. headers = MutableHeaders(scope=message) header_value = "%s=%s; %s" % ( self.session_cookie, "null; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;", self.security_flags, ) if self.domain: # pragma: no cover header_value += f"; domain={self.domain}" headers.append("Set-Cookie", header_value) await send(message) await self.app(scope, receive, send_wrapper)
def prepare_resolver(monkeypatch): resolvers._collect_predicate_names = lambda info: [ 'asn', 'prefix', 'ipLast' ] mock_database_query = Mock(spec=RPSLDatabaseQuery) monkeypatch.setattr('irrd.server.graphql.resolvers.RPSLDatabaseQuery', lambda **kwargs: mock_database_query) mock_database_query.columns = RPSLDatabaseQuery.columns mock_query_resolver = Mock(spec=QueryResolver) monkeypatch.setattr( 'irrd.server.graphql.resolvers.QueryResolver', lambda preloader, database_handler: mock_query_resolver) app = Mock(state=Mock( database_handler=Mock(spec=DatabaseHandler), preloader=Mock(spec=Preloader), )) app.state.database_handler.execute_query = lambda query, refresh_on_error: MOCK_RPSL_DB_RESULT info = Mock() info.context = {} info.field_nodes = [Mock(selection_set=Mock(selections=Mock()))] info.context['request'] = HTTPConnection({ 'type': 'http', 'client': ('127.0.0.1', '8000'), 'app': app, }) yield info, mock_database_query, mock_query_resolver
def get_request_object(scope, receive, send) -> Union[Request, HTTPConnection]: # here we instantiate HTTPConnection instead of a Request object # because only headers are needed so that's sufficient. # If you need the payload etc for your plugin # instantiate Request(scope, receive, send) return HTTPConnection(scope)
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: if scope["type"] not in ("http", "websocket"): # pragma: no cover await self.app(scope, receive, send) return connection = HTTPConnection(scope) initial_session_was_empty = True session_id = None if self.session_cookie in connection.cookies: session_id = connection.cookies[self.session_cookie] try: scope["session"] = await self.get_session(session_id) initial_session_was_empty = False except Exception: scope["session"] = {} else: scope["session"] = {} async def send_wrapper(message: Message) -> None: nonlocal session_id if message["type"] == "http.response.start": if scope["session"]: session_id = session_id or uuid.uuid4().hex # Persist session await self.save_session(session_id, scope["session"]) self.set_cookie(message=message, value=session_id) elif not initial_session_was_empty: # Clear session await self.delete_session(session_id) self.set_cookie(message=message, value="null", max_age=-1) await send(message) await self.app(scope, receive, send_wrapper)
async def authenticate(self, request: HTTPConnection): if "discord_id" not in request.session: request.session.pop("user", None) return user = request.session.get("user") if not user: uid = request.session["discord_id"] if uid not in settings.LADS: return user = { "discord_id": uid, "username": request.session["discord_username"], } request.session["user"] = user username, discord_id = ( user["username"], user["discord_id"], ) creds = ["authenticated"] return AuthCredentials(creds), User(username, discord_id)
async def authenticate(self, request: HTTPConnection): if "discord_id" not in request.session: request.session.pop("user", None) return user = request.session.get("user") if not user: db_user = await DBUser.get(request.session["discord_id"]) log.info("First time adding user info for %s, user: %s", request.session["discord_id"], db_user) if db_user is None: log.info("User %s was not in the database, rejecting", request.session["discord_id"]) request.session.pop("discord_id", None) return user = { "discord_id": db_user.discord_id, "is_admin": db_user.is_admin, "username": db_user.username, } request.session["user"] = user username, discord_id, is_admin = ( user["username"], user["discord_id"], user["is_admin"], ) creds = ["authenticated"] if is_admin: creds.append("admin") return AuthCredentials(creds), User(username, discord_id, is_admin)
async def post(self, request: HTTPConnection): id = request.path_params["id"] blog = await Blog.get(id) if blog is None: return abort(404, "Blog not found") form = await request.form() form = PostForm(form) if form.validate(): await blog.update_auto(title=form.title.data, tags=form.tags.data, content=form.content.data).apply() url = request.url_for("blog_view", slug=blog.slug) return redirect_response(url=url) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags()) return templates.TemplateResponse( "blog/edit.j2", { "request": request, "form": form, "blog": blog, "existing_images": images, "existing_tags": tags, }, )
async def post(self, request: HTTPConnection): form = await request.form() form = PostForm(form) is_valid = form.validate() if (await Blog.query.where(Blog.title == form.title.data).gino.first() is not None): is_valid = False form.title.errors.append( f"A blog with the title '{form.title.data}' already exists.") if is_valid: blog = await Blog.create_auto(title=form.title.data, tags=form.tags.data, content=form.content.data) url = request.url_for("blog_view", slug=blog.slug) return redirect_response(url=url) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags()) return templates.TemplateResponse( "blog/new.j2", { "request": request, "form": form, "existing_images": images, "existing_tags": tags, }, )
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: if scope['type'] not in ('http', 'websocket'): await self.app(scope, receive, send) return connection = HTTPConnection(scope) if self.session_header in connection.headers: data = connection.headers[self.session_header].encode('utf-8') try: data = self.signer.unsign(data, max_age=self.max_age) scope['session'] = json.loads(base64.b64decode(data)) except BadData: scope['session'] = {} else: scope['session'] = {} async def send_wrapper(message: Message) -> None: if message['type'] == 'http.response.start': if scope['session']: _data = base64.b64encode( json.dumps(scope['session']).encode('utf-8')) _data = self.signer.sign(_data) headers = MutableHeaders(scope=message) headers.append('session', _data.decode('utf-8')) await send(message) await self.app(scope, receive, send_wrapper)
async def index(request: HTTPConnection): posts = request.session.get("posts") if posts is None: posts = [] request.session["posts"] = posts form = PostForm() return templates.TemplateResponse( "main.j2", { "request": request, "form": form, "posts": posts, "post_create": request.url_for("post"), }, )
def setup_method(self): self.mock_request = HTTPConnection({ 'type': 'http', 'client': ('127.0.0.1', '8000'), }) self.endpoint = StatusEndpoint(scope=self.mock_request, receive=None, send=None)
async def bank_login(request: HTTPConnection): form = await request.form() form = LoginForm(form) r = redirect_response(url=request.url_for("bank")) r.set_cookie("username", form.user.data) return r
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: if scope["type"] in ("http", "websocket"): connection = HTTPConnection(scope) if "user" in connection.cookies: user_auth = connection.cookies["user"] headers = MutableHeaders(scope=scope) headers.setdefault("Authorization", user_auth) await self.app(scope, receive, send)
async def post(self, request: HTTPConnection): form = await request.form() form = ChallengeForm(form) is_valid = form.validate() if not slug(form.title.data): is_valid = False form.title.errors.append( "A valid url-safe name cannot be generated for this title.") if (await Challenge.query.where( sa.or_( Challenge.title == form.title.data, Challenge.slug == slug(form.title.data), )).gino.first() is not None): is_valid = False form.title.errors.append( f"A challenge with the title conflicting with '{form.title.data}' already exists." ) if is_valid: f_a = form.flag_or_answer.data flag, answer = (f_a, None) if form.is_flag.data else (None, f_a) challenge = await Challenge.create_auto( title=form.title.data, content=form.content.data, flag=flag, answer=answer, hidden=form.hidden.data, depreciated=form.depreciated.data, points=form.points.data, tags=form.tags.data, ) url = request.url_for("challenge_view", slug=challenge.slug) if not challenge.hidden: await log_create("challenge", challenge.title, request.user.username, url) return redirect_response(url=url) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags(include_hidden=True)) return templates.TemplateResponse( "challenge/new.j2", { "request": request, "form": form, "existing_images": images, "existing_tags": tags, }, )
async def encoded_existing_images(request: HTTPConnection) -> bytes: images = await get_existing_images(request.user.discord_id) images = [ { "filename": f"{id}.{ext}", "path": request.url_for("images", file_name=(id, ext)), } for (id, ext) in images ] return orjson.dumps(images)
async def post(self, request: HTTPConnection): id = request.path_params["id"] blog = await Blog.get(id) if blog is None: return abort(404, "Blog not found") if not can_edit(request, blog.author_id): return abort(400) form = await request.form() form = PostForm(form) is_valid = form.validate() if not slug(form.title.data): is_valid = False form.title.errors.append( "A valid url-safe name cannot be generated for this title.") if blog.title != blog.title.data: if (await Blog.query.where( sa.or_(Blog.title == form.title.data, Blog.slug == slug(form.title.data))).gino.first() is not None): is_valid = False form.title.errors.append( f"A blog with the title '{form.title.data}' already exists." ) if is_valid: await blog.update_auto(title=form.title.data, tags=form.tags.data, content=form.content.data).apply() url = request.url_for("blog_view", slug=blog.slug) await log_edit("blog", blog.title, request.user.username, url) return redirect_response(url=url) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags()) return templates.TemplateResponse( "blog/edit.j2", { "request": request, "form": form, "blog": blog, "existing_images": images, "existing_tags": tags, }, )
async def blog_delete(request: HTTPConnection): id = request.path_params["id"] blog = await Blog.get(id) if blog is None: return abort(404, "Blog not found") await blog.delete() return redirect_response(url=request.url_for("blog_index"))
def __init__(self, scope, receive, send, request_context=None): assert scope["type"] == "websocket" self._receive = receive self._send = send self.client_state = WebSocketState.CONNECTING self.application_state = WebSocketState.CONNECTING self.scope = scope self.request = HTTPConnection(scope) super().__init__(ws=self, request_context=request_context) self.on_close = None self.on_stop = None
async def post(self, request: HTTPConnection): form = await request.form() form = WriteupForm(form) is_valid = form.validate() if not slug(form.title.data): is_valid = False form.title.errors.append( "A valid url-safe name cannot be generated for this title." ) if ( await Writeup.query.where( sa.or_( Writeup.title == form.title.data, Writeup.slug == slug(form.title.data), ) ).gino.first() is not None ): is_valid = False form.title.errors.append( f"A writeup with the title conflicting with '{form.title.data}' already exists." ) if is_valid: writeup = await Writeup.create_auto( author_id=request.user.discord_id, title=form.title.data, tags=form.tags.data, content=form.content.data, private=form.private.data, ) url = request.url_for("writeups_view", slug=writeup.slug) await log_create("writeup", writeup.title, request.user.username, url) return redirect_response(url=url) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags(True)) return templates.TemplateResponse( "writeups/new.j2", { "request": request, "form": form, "existing_images": images, "existing_tags": tags, }, )
async def auth_cb(request: HTTPConnection): token = await oauth.discord.authorize_access_token(request) resp = await oauth.discord.get(DISCORD_API_BASE + "/users/@me", token=token) user = resp.json() log.info( "User %s#%s (%s) completed oauth", user["username"], user["discriminator"], user["id"], ) request.session["discord_id"] = int(user["id"]) return RedirectResponse(url="/")
async def bank_transfer(request: HTTPConnection): form = TransferForm(request.query_params) if not form.validate(): login_form = LoginForm() current_user = request.cookies.get("username") return templates.TemplateResponse( "bank.j2", { "request": request, "login_form": login_form, "transfer_form": form, "login_url": request.url_for("bank_login"), "transfer_url": request.url_for("bank_transfer"), "current_user": current_user, "transactions": [] if current_user is None else transactions[current_user], }, ) from_ = request.cookies.get("username") if from_ is None: raise HTTPException(status_code=401, detail="Not logged in") transaction = (from_, form.dest.data, form.amount.data) print(transaction) transactions[form.dest.data].append(transaction) transactions[from_].append(transaction) return redirect_response(url=request.url_for("bank"))
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: if scope["type"] not in ("http", "websocket"): # pragma: no cover await self.app(scope, receive, send) return connection = HTTPConnection(scope) initial_session_was_empty = True if self.session_cookie in connection.cookies: data = connection.cookies[self.session_cookie].encode("utf-8") try: data = self.signer.unsign(data, max_age=self.max_age) scope["session"] = json.loads(b64decode(data)) initial_session_was_empty = False except BadSignature: scope["session"] = {} else: scope["session"] = {} async def send_wrapper(message: Message) -> None: if message["type"] == "http.response.start": if scope["session"]: # We have session data to persist. data = b64encode( json.dumps(scope["session"]).encode("utf-8")) data = self.signer.sign(data) headers = MutableHeaders(scope=message) header_value = "{session_cookie}={data}; path={path}; {max_age}{security_flags}".format( # noqa E501 session_cookie=self.session_cookie, data=data.decode("utf-8"), path=self.path, max_age=f"Max-Age={self.max_age}; " if self.max_age else "", security_flags=self.security_flags, ) headers.append("Set-Cookie", header_value) elif not initial_session_was_empty: # The session has been cleared. headers = MutableHeaders(scope=message) header_value = "{session_cookie}={data}; path={path}; {expires}{security_flags}".format( # noqa E501 session_cookie=self.session_cookie, data="null", path=self.path, expires="expires=Thu, 01 Jan 1970 00:00:00 GMT; ", security_flags=self.security_flags, ) headers.append("Set-Cookie", header_value) await send(message) await self.app(scope, receive, send_wrapper)
async def post(request: HTTPConnection): form = await request.form() form = PostForm(form) name = form.name.data message = form.message.data posts = request.session.get("posts") if posts is None: posts = [] request.session["posts"] = posts posts.append((name, message)) return templates.TemplateResponse( "main.j2", { "request": request, "form": form, "posts": posts, "post_create": request.url_for("post"), }, )
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: if scope["type"] not in ("http", "websocket"): # pragma: no cover await self.app(scope, receive, send) return connection = HTTPConnection(scope) initial_session_was_empty = True if self.session_cookie in connection.cookies: data = connection.cookies[self.session_cookie].encode("utf-8") try: data = self.signer.unsign(data, max_age=self.max_age) scope["session"] = json.loads(b64decode(data)) initial_session_was_empty = False except (BadTimeSignature, SignatureExpired): scope["session"] = {} else: scope["session"] = {} async def send_wrapper(message: Message) -> None: if message["type"] == "http.response.start": path = scope.get("root_path", "") or "/" if scope["session"]: # We have session data to persist. data = b64encode( json.dumps(scope["session"]).encode("utf-8")) data = self.signer.sign(data) headers = MutableHeaders(scope=message) header_value = "%s=%s; path=%s; Max-Age=%d; %s" % ( self.session_cookie, data.decode("utf-8"), path, self.max_age, self.security_flags, ) headers.append("Set-Cookie", header_value) elif not initial_session_was_empty: # The session has been cleared. headers = MutableHeaders(scope=message) header_value = "{}={}; {}".format( self.session_cookie, f"null; path={path}; expires=Thu, 01 Jan 1970 00:00:00 GMT;", self.security_flags, ) headers.append("Set-Cookie", header_value) await send(message) await self.app(scope, receive, send_wrapper)
async def challenge_delete(request: HTTPConnection): id = request.path_params["id"] challenge = await Challenge.get(id) if challenge is None: return abort(404, "Challenge not found") if not can_edit(request): return abort(400) await challenge.delete() await log_delete("challenge", challenge.title, request.user.username) return redirect_response(url=request.url_for("challenge_index"))