mirror of
https://github.com/valitydev/redash.git
synced 2024-11-06 17:15:17 +00:00
5afd0554d0
* add flask-wtf * add CSRF tokens to all static forms * add CSRF tokens to all axios requests * disable CSRF validation in unit tests * support CSRF-protected requests in *most* cypress tests * don't enfroce CSRF checks by default * avoid CSRF enforcement in unit tests * remove redundant spread * some camel casing hiccups * always yield the CSRF cookie, but avoid enforcing it if CSRF toggle is off * Restyled by prettier (#5056) Co-authored-by: Restyled.io <commits@restyled.io> * set a CSRF header only if cookie is present * enforce CSRF in CI * install lodash directly for Cypress * install request-cookies directly for Cypress. We should probably start loading package.json deps * enable CSRF support when logout and login happen within the same spec Co-authored-by: restyled-io[bot] <32688539+restyled-io[bot]@users.noreply.github.com> Co-authored-by: Restyled.io <commits@restyled.io>
144 lines
3.7 KiB
Python
144 lines
3.7 KiB
Python
import os
|
|
import datetime
|
|
import logging
|
|
from unittest import TestCase
|
|
from contextlib import contextmanager
|
|
|
|
os.environ["REDASH_REDIS_URL"] = os.environ.get(
|
|
"REDASH_REDIS_URL", "redis://localhost:6379/0"
|
|
).replace("/0", "/5")
|
|
# Use different url for RQ to avoid DB being cleaned up:
|
|
os.environ["RQ_REDIS_URL"] = os.environ.get(
|
|
"REDASH_REDIS_URL", "redis://localhost:6379/0"
|
|
).replace("/5", "/6")
|
|
|
|
# Dummy values for oauth login
|
|
os.environ["REDASH_GOOGLE_CLIENT_ID"] = "dummy"
|
|
os.environ["REDASH_GOOGLE_CLIENT_SECRET"] = "dummy"
|
|
os.environ["REDASH_MULTI_ORG"] = "true"
|
|
|
|
# Make sure rate limit is enabled
|
|
os.environ["REDASH_RATELIMIT_ENABLED"] = "true"
|
|
|
|
os.environ["REDASH_ENFORCE_CSRF"] = "false"
|
|
|
|
from redash import limiter, redis_connection
|
|
from redash.app import create_app
|
|
from redash.models import db
|
|
from redash.utils import json_dumps, json_loads
|
|
from tests.factories import Factory, user_factory
|
|
|
|
|
|
logging.disable(logging.INFO)
|
|
logging.getLogger("metrics").setLevel(logging.ERROR)
|
|
|
|
|
|
def authenticate_request(c, user):
|
|
with c.session_transaction() as sess:
|
|
sess["user_id"] = user.get_id()
|
|
|
|
|
|
@contextmanager
|
|
def authenticated_user(c, user=None):
|
|
if not user:
|
|
user = user_factory.create()
|
|
db.session.commit()
|
|
authenticate_request(c, user)
|
|
|
|
yield user
|
|
|
|
|
|
class BaseTestCase(TestCase):
|
|
def setUp(self):
|
|
self.app = create_app()
|
|
self.db = db
|
|
self.app.config["TESTING"] = True
|
|
limiter.enabled = False
|
|
self.app_ctx = self.app.app_context()
|
|
self.app_ctx.push()
|
|
db.session.close()
|
|
db.drop_all()
|
|
db.create_all()
|
|
self.factory = Factory()
|
|
self.client = self.app.test_client()
|
|
|
|
def tearDown(self):
|
|
db.session.remove()
|
|
db.get_engine(self.app).dispose()
|
|
self.app_ctx.pop()
|
|
redis_connection.flushdb()
|
|
|
|
def make_request(
|
|
self,
|
|
method,
|
|
path,
|
|
org=None,
|
|
user=None,
|
|
data=None,
|
|
is_json=True,
|
|
follow_redirects=False,
|
|
):
|
|
if user is None:
|
|
user = self.factory.user
|
|
|
|
if org is None:
|
|
org = self.factory.org
|
|
|
|
if org is not False:
|
|
path = "/{}{}".format(org.slug, path)
|
|
|
|
if user:
|
|
authenticate_request(self.client, user)
|
|
|
|
method_fn = getattr(self.client, method.lower())
|
|
headers = {}
|
|
|
|
if data and is_json:
|
|
data = json_dumps(data)
|
|
|
|
if is_json:
|
|
content_type = "application/json"
|
|
else:
|
|
content_type = None
|
|
|
|
response = method_fn(
|
|
path,
|
|
data=data,
|
|
headers=headers,
|
|
content_type=content_type,
|
|
follow_redirects=follow_redirects,
|
|
)
|
|
return response
|
|
|
|
def get_request(self, path, org=None, headers=None):
|
|
if org:
|
|
path = "/{}{}".format(org.slug, path)
|
|
|
|
return self.client.get(path, headers=headers)
|
|
|
|
def post_request(self, path, data=None, org=None, headers=None):
|
|
if org:
|
|
path = "/{}{}".format(org.slug, path)
|
|
|
|
return self.client.post(path, data=data, headers=headers)
|
|
|
|
def assertResponseEqual(self, expected, actual):
|
|
for k, v in expected.items():
|
|
if isinstance(v, datetime.datetime) or isinstance(
|
|
actual[k], datetime.datetime
|
|
):
|
|
continue
|
|
|
|
if isinstance(v, list):
|
|
continue
|
|
|
|
if isinstance(v, dict):
|
|
self.assertResponseEqual(v, actual[k])
|
|
continue
|
|
|
|
self.assertEqual(
|
|
v,
|
|
actual[k],
|
|
"{} not equal (expected: {}, actual: {}).".format(k, v, actual[k]),
|
|
)
|