separate backend base url from frontend (#1819)

* separate backend base url from frontend

This is needed for auth, and to support a different location for the backend api server,
than the frontend.

 part of chanzuckerberg/cellxgene#1778

new server config parameters:   app__api_base_url,   app__web_base_url

Also changed api_base_url in the oauth config section to "oauth_api_base_url" to
be less confusing with the app's api_base_url

Other minor changes:

changed how the jwt decode options are handled.
Previously they needed to be set in a test case, and there was some extra logic to handle that.
Now they are handled through comfig parameters, which makes it more general.

Also, add a feature to set the CORS support credentials, which seems
to be necessary for the backend/frontend separation, at least when run
locally.  This part is sort of experimental, and may be removed or changed later.
This commit is contained in:
bmccandless
2020-09-11 09:50:16 -07:00
committed by GitHub
parent 3f20f4a1f4
commit a7a4580944
8 changed files with 243 additions and 121 deletions
+30 -6
View File
@@ -417,6 +417,7 @@ class ServerConfig(BaseConfig):
dictval_cases = [
("app", "csp_directives"),
("authentication", "params_oauth", "cookie"),
("authentication", "params_oauth", "jwt_decode_options"),
("adaptor", "cxg_adaptor", "tiledb_ctx"),
("multi_dataset", "dataroot"),
]
@@ -434,13 +435,18 @@ class ServerConfig(BaseConfig):
self.app__generate_cache_control_headers = dc["app"]["generate_cache_control_headers"]
self.app__server_timing_headers = dc["app"]["server_timing_headers"]
self.app__csp_directives = dc["app"]["csp_directives"]
self.app__cors_supports_credentials = dc["app"]["cors_supports_credentials"]
self.app__api_base_url = dc["app"]["api_base_url"]
self.app__web_base_url = dc["app"]["web_base_url"]
self.authentication__type = dc["authentication"]["type"]
self.authentication__params_oauth__api_base_url = dc["authentication"]["params_oauth"]["api_base_url"]
self.authentication__params_oauth__oauth_api_base_url = dc["authentication"]["params_oauth"][
"oauth_api_base_url"
]
self.authentication__params_oauth__client_id = dc["authentication"]["params_oauth"]["client_id"]
self.authentication__params_oauth__client_secret = dc["authentication"]["params_oauth"]["client_secret"]
self.authentication__params_oauth__callback_base_url = \
dc["authentication"]["params_oauth"]["callback_base_url"]
self.authentication__params_oauth__jwt_decode_options = dc["authentication"]["params_oauth"][
"jwt_decode_options"]
self.authentication__params_oauth__session_cookie = dc["authentication"]["params_oauth"]["session_cookie"]
self.authentication__params_oauth__cookie = dc["authentication"]["params_oauth"]["cookie"]
@@ -500,7 +506,10 @@ class ServerConfig(BaseConfig):
self.check_attr("app__flask_secret_key", (type(None), str))
self.check_attr("app__generate_cache_control_headers", bool)
self.check_attr("app__server_timing_headers", bool)
self.check_attr("app__cors_supports_credentials", bool)
self.check_attr("app__csp_directives", (type(None), dict))
self.check_attr("app__api_base_url", (type(None), str))
self.check_attr("app__web_base_url", (type(None), str))
if self.app__port:
try:
@@ -549,15 +558,18 @@ class ServerConfig(BaseConfig):
elif not isinstance(v, str):
raise ConfigurationError("CSP directive value must be a string or list of strings.")
if self.app__web_base_url is None:
self.app__web_base_url = self.app__api_base_url
def handle_authentication(self, context):
self.check_attr("authentication__type", (type(None), str))
# oauth
ptypes = str if self.authentication__type == "oauth" else (type(None), str)
self.check_attr("authentication__params_oauth__api_base_url", ptypes)
self.check_attr("authentication__params_oauth__oauth_api_base_url", ptypes)
self.check_attr("authentication__params_oauth__client_id", ptypes)
self.check_attr("authentication__params_oauth__client_secret", ptypes)
self.check_attr("authentication__params_oauth__callback_base_url", (type(None), str))
self.check_attr("authentication__params_oauth__jwt_decode_options", (type(None), dict))
self.check_attr("authentication__params_oauth__session_cookie", bool)
if self.authentication__params_oauth__session_cookie:
@@ -743,6 +755,18 @@ class ServerConfig(BaseConfig):
return False
return value > limit_value
def get_api_base_url(self):
if self.app__api_base_url == "local":
return f"http://{self.app__host}:{self.app__port}"
return self.app__api_base_url
def get_web_base_url(self):
if self.app__web_base_url == "local":
return f"http://{self.app__host}:{self.app__port}"
if self.app__web_base_url is None:
return self.get_api_base_url()
return self.app__web_base_url
class DatasetConfig(BaseConfig):
"""Manages the config attribute associated with a dataset."""
@@ -769,7 +793,7 @@ class DatasetConfig(BaseConfig):
self.user_annotations__ontology__obo_location = dc["user_annotations"]["ontology"]["obo_location"]
self.user_annotations__hosted_tiledb_array__db_uri = dc["user_annotations"]["hosted_tiledb_array"]["db_uri"]
self.user_annotations__hosted_tiledb_array__hosted_file_directory = \
dc["user_annotations"]["hosted_tiledb_array"]["hosted_file_directory"] # noqa E501
dc["user_annotations"][ "hosted_tiledb_array" ][ "hosted_file_directory" ] # noqa E501
self.embeddings__names = dc["embeddings"]["names"]
self.embeddings__enable_reembedding = dc["embeddings"]["enable_reembedding"]