Skip to content

Commit

Permalink
AUTHORIZATIONS...
Browse files Browse the repository at this point in the history
Now setting the basic authorization in defaults.py (removing authoriztions.yaml), and adjusting the processing of local defaults.
  • Loading branch information
mbaudis committed Feb 23, 2024
1 parent 2015f2f commit 3e9c514
Show file tree
Hide file tree
Showing 14 changed files with 884 additions and 46 deletions.
8 changes: 7 additions & 1 deletion bycon/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,17 @@
# to be modified during execution ##############################################
################################################################################

AUTHORIZATIONS = {
"anonymous": {"default": "boolean"},
"local": {"default": "record"}
}

BYC = {
"DEBUG_MODE": False,
"TEST_MODE": False,
"ERRORS": [],
"WARNINGS": []
"WARNINGS": [],
"USER": "anonymous"
}

# collection object for cmd arguments and web parameters (depending on the ENV)
Expand Down
9 changes: 7 additions & 2 deletions bycon/definitions/argument_definitions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ requested_granularity:
cmdFlags:
- --requestedGranularity
description: The requested granularity of the beacon
default: record

request_entity_path_id:
type: string
Expand Down Expand Up @@ -345,8 +346,12 @@ output:
cmdFlags:
- --output
description: >-
special output format; command line processing uses some predefined text as
standard, but options are e.g. json or pgxseg
For defining a special output format, mostly for `byconaut` services use.
Examples:
* `cnvstats`, for `analyses`, to present some CNV statistics
* `pgxseg`, using the `.pgxseg` variant file format
* `text`, for some services to deliver a text table instead of JSON
include_handovers:
type: boolean
Expand Down
4 changes: 0 additions & 4 deletions bycon/definitions/authorizations.yaml

This file was deleted.

5 changes: 0 additions & 5 deletions bycon/definitions/beacon_defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ defaults:
default_dataset_id: examplez
request_path_root: beacon
request_entity_path_id: info
assembly_id: GRCh38
response_schema: beaconInfoResponse
include_resultset_responses: HIT
requested_granularity: record
returned_granularity: record
user_name: anonymous
pagination:
skip: 0
limit: 200
response_entity:
entity_type: info
response_schema: beaconInfoResponse
Expand Down
6 changes: 2 additions & 4 deletions bycon/definitions/variant_request_definitions.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
################################################################################
#
# TODO: use definitions directly from model -> genomicVariations -> requestParameters
# TODO: Beacon scouts for VQS ...
#
################################################################################

variant_pars:
request_pars:
- assembly_id
- reference_name
- mate_name
Expand All @@ -18,8 +18,6 @@ variant_pars:
- gene_id
- aminoacid_change
- genomic_allele_short_form
- cyto_bands # custom yet
- chro_bases # custom yet

# As long as there are no variant query schemas to define valid Beacon
# variant parameter combinations the `request_types` here provide sets
Expand Down
36 changes: 23 additions & 13 deletions bycon/lib/beacon_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,57 @@

def set_user_name(byc):
"""
The default user is `anonymous`. If the environment is local the `local` user
will be assumed - but can be overwritten later, e.g. for testing purposes.
The default user is `anonymous`. Their access granularity is defined in
`config.py` => `AUTH_DEFAULTS`.
If the environment is local the `local` user will be assumed - but can be
overwritten later, e.g. for testing purposes.
"""
# local user has full permissions
if "local" in ENV:
byc.update({"user_name": "local"})
return
un = BYC_PARS.get("user", "anonymous")
if un in byc.get("authorizations", {}):
byc.update({"user_name": un})
BYC.update({"USER": "local"})
elif (un := BYC_PARS.get("user_name", "anonymous")) in byc.get("authorizations", {}):
BYC.update({"USER": un})


################################################################################

def set_returned_granularities(byc):
rg = BYC_PARS.get("requested_granularity", "record")
un = byc.get("user_name", "anonymous")
auth = byc.get("authorizations", {})
ds_ids = byc.get("dataset_ids", [])

for ak, av in auth.items():
AUTHORIZATIONS.update({ak: av})

g_l_s = [0]
r_g_l = GRANULARITY_LEVELS.get(rg, 0)

if not "authorized_granularities" in byc:
byc.update({"authorized_granularities": {}})
for ds_id in byc["dataset_ids"]:

for ds_id in ds_ids:
byc["authorized_granularities"].update({ds_id: rg})
ugs = auth.get(un, {})

# the user is checked against predefined authorizations
if not (ugs := auth.get(BYC["USER"])):
continue
prdbug(f'USER {BYC["USER"]} - authorizations {ugs}')

g_l_l = ugs.get("default", "___none___")
if ds_id in ugs:
g_l_l = ugs[ds_id]
elif "default" in ugs:
g_l_l = ugs["default"]

d_g_l = GRANULARITY_LEVELS.get(g_l_l, 0)
if d_g_l <= r_g_l:
byc["authorized_granularities"].update({ds_id: g_l_l})
g_l_s.append(d_g_l)

m_g_l = max(g_l_s)

prdbug(f'Granularity levels: {g_l_s} - max: {m_g_l} - requested: {r_g_l}')

if m_g_l < r_g_l:
prdbug("Warning: Requested granularity exceeds user authorization - using a maximum of %s" % byc["returned_granularity"])
prdbug(f'Warning: Requested granularity exceeds user authorization - using a maximum of {byc["returned_granularity"]}')
byc.update({"returned_granularity": list(GRANULARITY_LEVELS.keys())[m_g_l]})
else:
byc.update({"returned_granularity": list(GRANULARITY_LEVELS.keys())[r_g_l]})
6 changes: 3 additions & 3 deletions bycon/lib/beacon_response_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def __init__(self, byc: dict):
self.user_name = byc.get("user_name", "anonymous")
self.entity_defaults = self.beacon_defaults.get("entity_defaults", {"info":{}})
self.response_schema = byc["response_schema"]
self.returned_granularity = BYC_PARS.get("requested_granularity", "record")
self.returned_granularity = byc.get("returned_granularity", "boolean")
self.include_handovers = BYC_PARS.get("include_handovers", False)
self.beacon_schema = byc["response_entity"].get("beacon_schema", "___none___")
self.record_queries = {}
Expand All @@ -138,7 +138,7 @@ def resultsetResponse(self):

self.data_response["response"].update({"result_sets": self.result_sets})
self.__resultset_response_update_summaries()
self.__resultSetResponse_force_granularities()
self.__resultSetResponse_force_autorized_granularities()

b_h_o = self.data_response.get("beacon_handovers", [])
if len(b_h_o) < 1:
Expand Down Expand Up @@ -215,7 +215,7 @@ def __check_switch_to_error_response(self):

# -------------------------------------------------------------------------#

def __resultSetResponse_force_granularities(self):
def __resultSetResponse_force_autorized_granularities(self):
prdbug(f'authorized_granularities: {self.authorized_granularities}')
for rs in self.data_response["response"]["result_sets"]:
rs_granularity = self.authorized_granularities.get(rs["id"], "boolean")
Expand Down
3 changes: 0 additions & 3 deletions bycon/lib/bycon_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,11 @@ def mongo_test_mode_query(db_name, coll_name, test_mode_count=5):
################################################################################

def assign_nested_value(parent, dotted_key, v, parameter_definitions={}):

parameter_type = parameter_definitions.get("type", "string")
parameter_default = parameter_definitions.get("default")

if v is None:
if parameter_default:
v = parameter_default

if v is None:
return parent

Expand Down
2 changes: 1 addition & 1 deletion bycon/lib/parse_variant_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def parse_variants(byc):
################################################################################

def __parse_variant_parameters(byc):
v_p_s = byc["variant_request_definitions"].get("variant_pars", [])
v_p_s = byc["variant_request_definitions"].get("request_pars", [])
a_defs = byc.get("argument_definitions", {})
v_t_defs = byc["variant_type_definitions"]

Expand Down
5 changes: 1 addition & 4 deletions bycon/lib/response_remapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,15 @@ def remap_variants(r_s_res, byc):
def remap_analyses(r_s_res, byc):
if not "analysis" in byc["response_entity_id"]:
return r_s_res

pop_keys = ["info", "provenance", "cnv_statusmaps", "cnv_chro_stats", "cnv_stats"]

if "cnvstats" in byc.get("output", "___none___").lower():
if "cnvstats" in BYC_PARS.get("output", "___none___").lower():
pop_keys = ["info", "provenance", "cnv_statusmaps"]

for cs_i, cs_r in enumerate(r_s_res):
# TODO: REMOVE VERIFIER HACKS
r_s_res[cs_i].update({"pipeline_name": "progenetix", "analysis_date": "1967-11-11"})
for k in pop_keys:
r_s_res[cs_i].pop(k, None)

return r_s_res


Expand Down
13 changes: 7 additions & 6 deletions bycon/lib/variant_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
################################################################################

class ByconVariant:

def __init__(self, byc, variant={}):
"""
# Class `ByconVariant`
The class provides methods for the conversion ofgenomic variant objects
The class provides methods for the conversion of genomic variant objects
with slight variations in their input parameters to a "canonical" intermediary
`byc_variant` type, and from there then map per function to other formats
(such as the Progenetix database format, VCF or VRS).
Expand All @@ -27,21 +27,21 @@ def __init__(self, byc, variant={}):
Progenetix platform and does not cover some use cases outside of Progenetix
and Beacon "common use" scenarios (as of Beacon v2 / 2023).
"""

self.byc = byc
self.byc_variant = {}
self.pgx_variant = {}
self.vrs_variant = {}
self.vcf_variant = {}
self.pgxseg_variant = {}

self.ChroNames = ChroNames()

self.variant_types = byc.get("variant_type_definitions", {})

# datatable mappings contain the "name to place in object" definitions
# these are in essence identical to the `db_key` mappings in
# `argument_definitions` but logically different (query vs. defiition; `default`...)
d_m = byc["datatable_mappings"].get("definitions", {})
d_m_v = d_m.get("genomicVariant", {})
self.variant_mappings = d_m_v.get("parameters", {})

self.vrs_allele = object_instance_from_schema_name(byc, "VRSallele", "")
self.vrs_cnv = object_instance_from_schema_name(byc, "VRScopyNumberChange", "")

Expand Down Expand Up @@ -155,6 +155,7 @@ def vrsVariant(self, variant={}):
self.vrs_variant.update(vrs_v)
return self.vrs_variant


# -------------------------------------------------------------------------#

def __vrs_allele(self):
Expand Down
Loading

0 comments on commit 3e9c514

Please sign in to comment.