mirror of
https://github.com/getredash/redash.git
synced 2025-12-19 17:37:19 -05:00
Merge branch 'master' into dependabot/npm_and_yarn/pbkdf2-3.1.3
This commit is contained in:
2
.github/workflows/preview-image.yml
vendored
2
.github/workflows/preview-image.yml
vendored
@@ -121,7 +121,7 @@ jobs:
|
||||
context: .
|
||||
build-args: |
|
||||
test_all_deps=true
|
||||
outputs: type=image,push-by-digest=true,push=true
|
||||
outputs: type=image,push-by-digest=false,push=true
|
||||
cache-from: type=gha,scope=${{ matrix.arch }}
|
||||
cache-to: type=gha,mode=max,scope=${{ matrix.arch }}
|
||||
env:
|
||||
|
||||
@@ -4,7 +4,7 @@ import requests
|
||||
from authlib.integrations.flask_client import OAuth
|
||||
from flask import Blueprint, flash, redirect, request, session, url_for
|
||||
|
||||
from redash import models
|
||||
from redash import models, settings
|
||||
from redash.authentication import (
|
||||
create_and_login_user,
|
||||
get_next_path,
|
||||
@@ -29,6 +29,41 @@ def verify_profile(org, profile):
|
||||
return False
|
||||
|
||||
|
||||
def get_user_profile(access_token, logger):
|
||||
headers = {"Authorization": f"OAuth {access_token}"}
|
||||
response = requests.get("https://www.googleapis.com/oauth2/v1/userinfo", headers=headers)
|
||||
|
||||
if response.status_code == 401:
|
||||
logger.warning("Failed getting user profile (response code 401).")
|
||||
return None
|
||||
|
||||
return response.json()
|
||||
|
||||
|
||||
def build_redirect_uri():
|
||||
scheme = settings.GOOGLE_OAUTH_SCHEME_OVERRIDE or None
|
||||
return url_for(".callback", _external=True, _scheme=scheme)
|
||||
|
||||
|
||||
def build_next_path(org_slug=None):
|
||||
next_path = request.args.get("next")
|
||||
if not next_path:
|
||||
if org_slug is None:
|
||||
org_slug = session.get("org_slug")
|
||||
|
||||
scheme = None
|
||||
if settings.GOOGLE_OAUTH_SCHEME_OVERRIDE:
|
||||
scheme = settings.GOOGLE_OAUTH_SCHEME_OVERRIDE
|
||||
|
||||
next_path = url_for(
|
||||
"redash.index",
|
||||
org_slug=org_slug,
|
||||
_external=True,
|
||||
_scheme=scheme,
|
||||
)
|
||||
return next_path
|
||||
|
||||
|
||||
def create_google_oauth_blueprint(app):
|
||||
oauth = OAuth(app)
|
||||
|
||||
@@ -36,23 +71,12 @@ def create_google_oauth_blueprint(app):
|
||||
blueprint = Blueprint("google_oauth", __name__)
|
||||
|
||||
CONF_URL = "https://accounts.google.com/.well-known/openid-configuration"
|
||||
oauth = OAuth(app)
|
||||
oauth.register(
|
||||
name="google",
|
||||
server_metadata_url=CONF_URL,
|
||||
client_kwargs={"scope": "openid email profile"},
|
||||
)
|
||||
|
||||
def get_user_profile(access_token):
|
||||
headers = {"Authorization": "OAuth {}".format(access_token)}
|
||||
response = requests.get("https://www.googleapis.com/oauth2/v1/userinfo", headers=headers)
|
||||
|
||||
if response.status_code == 401:
|
||||
logger.warning("Failed getting user profile (response code 401).")
|
||||
return None
|
||||
|
||||
return response.json()
|
||||
|
||||
@blueprint.route("/<org_slug>/oauth/google", endpoint="authorize_org")
|
||||
def org_login(org_slug):
|
||||
session["org_slug"] = current_org.slug
|
||||
@@ -60,9 +84,9 @@ def create_google_oauth_blueprint(app):
|
||||
|
||||
@blueprint.route("/oauth/google", endpoint="authorize")
|
||||
def login():
|
||||
redirect_uri = url_for(".callback", _external=True)
|
||||
redirect_uri = build_redirect_uri()
|
||||
|
||||
next_path = request.args.get("next", url_for("redash.index", org_slug=session.get("org_slug")))
|
||||
next_path = build_next_path()
|
||||
logger.debug("Callback url: %s", redirect_uri)
|
||||
logger.debug("Next is: %s", next_path)
|
||||
|
||||
@@ -86,7 +110,7 @@ def create_google_oauth_blueprint(app):
|
||||
flash("Validation error. Please retry.")
|
||||
return redirect(url_for("redash.login"))
|
||||
|
||||
profile = get_user_profile(access_token)
|
||||
profile = get_user_profile(access_token, logger)
|
||||
if profile is None:
|
||||
flash("Validation error. Please retry.")
|
||||
return redirect(url_for("redash.login"))
|
||||
@@ -110,7 +134,9 @@ def create_google_oauth_blueprint(app):
|
||||
if user is None:
|
||||
return logout_and_redirect_to_index()
|
||||
|
||||
unsafe_next_path = session.get("next_url") or url_for("redash.index", org_slug=org.slug)
|
||||
unsafe_next_path = session.get("next_url")
|
||||
if not unsafe_next_path:
|
||||
unsafe_next_path = build_next_path(org.slug)
|
||||
next_path = get_next_path(unsafe_next_path)
|
||||
|
||||
return redirect(next_path)
|
||||
|
||||
@@ -564,7 +564,7 @@ class Query(ChangeTrackingMixin, TimestampMixin, BelongsToOrgMixin, db.Model):
|
||||
db.session.query(tag_column, usage_count)
|
||||
.group_by(tag_column)
|
||||
.filter(Query.id.in_(queries.options(load_only("id"))))
|
||||
.order_by(usage_count.desc())
|
||||
.order_by(tag_column)
|
||||
)
|
||||
return query
|
||||
|
||||
@@ -1137,7 +1137,7 @@ class Dashboard(ChangeTrackingMixin, TimestampMixin, BelongsToOrgMixin, db.Model
|
||||
db.session.query(tag_column, usage_count)
|
||||
.group_by(tag_column)
|
||||
.filter(Dashboard.id.in_(dashboards.options(load_only("id"))))
|
||||
.order_by(usage_count.desc())
|
||||
.order_by(tag_column)
|
||||
)
|
||||
return query
|
||||
|
||||
|
||||
@@ -313,6 +313,10 @@ class BigQuery(BaseSQLQueryRunner):
|
||||
queries = []
|
||||
for dataset in datasets:
|
||||
dataset_id = dataset["datasetReference"]["datasetId"]
|
||||
location = dataset["location"]
|
||||
if self._get_location() and location != self._get_location():
|
||||
logger.debug("dataset location is different: %s", location)
|
||||
continue
|
||||
query = query_base.format(dataset_id=dataset_id)
|
||||
queries.append(query)
|
||||
|
||||
|
||||
@@ -136,6 +136,13 @@ FEATURE_POLICY = os.environ.get("REDASH_FEATURE_POLICY", "")
|
||||
|
||||
MULTI_ORG = parse_boolean(os.environ.get("REDASH_MULTI_ORG", "false"))
|
||||
|
||||
# If Redash is behind a proxy it might sometimes receive a X-Forwarded-Proto of HTTP
|
||||
# even if your actual Redash URL scheme is HTTPS. This will cause Flask to build
|
||||
# the OAuth redirect URL incorrectly thus failing auth. This is especially common if
|
||||
# you're behind a SSL/TCP configured AWS ELB or similar.
|
||||
# This setting will force the URL scheme.
|
||||
GOOGLE_OAUTH_SCHEME_OVERRIDE = os.environ.get("REDASH_GOOGLE_OAUTH_SCHEME_OVERRIDE", "")
|
||||
|
||||
GOOGLE_CLIENT_ID = os.environ.get("REDASH_GOOGLE_CLIENT_ID", "")
|
||||
GOOGLE_CLIENT_SECRET = os.environ.get("REDASH_GOOGLE_CLIENT_SECRET", "")
|
||||
GOOGLE_OAUTH_ENABLED = bool(GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET)
|
||||
|
||||
Reference in New Issue
Block a user