import json import os from sqlalchemy import and_, or_ from sqlalchemy.orm import aliased from atlas_um.logs import logger from atlas_um.pgdb import ( ClaimName, ClaimValue, ResourceGroup, pgdb, dna_account_claim_table, ) from atlas_um.settings import Settings FIXTURES_DIR = "products_claims_fixtures" def init_products_claims(): current_dir_path = os.path.dirname(os.path.abspath(__file__)) fixtures_dir_path = os.path.join(current_dir_path, FIXTURES_DIR) for filename in os.listdir(fixtures_dir_path): if filename.endswith(".json"): with open(f"{fixtures_dir_path}/{filename}", "r") as f: fixture = json.load(f) _add_resource_groups(fixture) def _add_resource_groups(fixture): if not fixture.get("resource_groups"): _add_resource_group_claim_names(None, fixture) return for item in fixture.get("resource_groups", []): namespace_url = item.get("namespace_url") name = item.get("name") resource_group = ResourceGroup.query.filter_by( namespace_url=namespace_url ).first() if resource_group is None: resource_group = ResourceGroup( name=name, namespace_url=namespace_url, external_id=namespace_url, session_ttl=Settings.DEFAULT_REFRESH_TOKEN_TTL, active_session_ttl=Settings.DEFAULT_REFRESH_TOKEN_TTL, ) pgdb.session.add(resource_group) try: pgdb.session.commit() except Exception: logger.bind(resource_group=namespace_url).exception( "Data init exception" ) continue _add_resource_group_claim_names(resource_group, fixture) def _add_resource_group_claim_names(resource_group, fixture): if resource_group: filtered_items = ( cn for cn in fixture.get("claim_names", []) if cn.get("resource_group") == resource_group.namespace_url ) else: filtered_items = fixture.get("claim_names", []) for item in filtered_items: path = item.get("path") friendly = item.get("friendly") claim_values_serializer = item.get("claim_values_serializer") claim_values_source = item.get("claim_values_source") images_url = item.get("images_url") or "" parent = item.get("parent") if claim_values_source: claim_values_source = ClaimName.query.filter( ClaimName.resource_group_id == None, # noqa ClaimName.path == claim_values_source, ).first() if parent: parent = ClaimName.query.filter( ClaimName.resource_group_id == None, # noqa ClaimName.path == parent, ).first() claim_name = ClaimName.query.filter_by( resource_group=resource_group, path=path ).first() if claim_name is None: claim_name = ClaimName( resource_group=resource_group, path=path, friendly=friendly, claim_values_serializer=claim_values_serializer, external_id=path, claim_values_source=claim_values_source, parent=parent, images_url=images_url, ) pgdb.session.add(claim_name) else: claim_name.friendly = friendly claim_name.claim_values_serializer = claim_values_serializer claim_name.claim_values_source = claim_values_source claim_name.images_url = images_url claim_name.parent = parent try: pgdb.session.commit() except Exception: logger.bind(claim_name=path).exception("Data init exception") continue _add_claim_name_values(claim_name, fixture) def _add_claim_name_values(claim_name, fixture): if claim_name.resource_group: filtered_items = ( cv for cv in fixture.get("claim_values", []) if cv.get("resource_group") == claim_name.resource_group.namespace_url and cv.get("claim_name") == claim_name.path ) else: filtered_items = ( cv for cv in fixture.get("claim_values", []) if cv.get("claim_name") == claim_name.path ) for item in filtered_items: friendly = item.get("friendly") components = item.get("components") external_id = item.get("external_id") claim_value = ClaimValue.query.filter( ClaimValue.claim_name == claim_name, or_( ClaimValue.friendly == friendly, ClaimValue.external_id == str(external_id), ), ).first() if claim_value is None: claim_value = ClaimValue( claim_name=claim_name, friendly=friendly, components=components, external_id=external_id, ) pgdb.session.add(claim_value) else: claim_value.components = components claim_value.external_id = external_id try: pgdb.session.commit() except Exception: logger.bind(claim_value=friendly).exception("Data init exception") continue def _convert_to_global_claim_values(): """ Updating assigned claims from own to global for accounts where needed. """ global_cv = aliased(ClaimValue) mapping_query = ( pgdb.session.query( ClaimValue.id, global_cv.id, ClaimName.id, ) .select_from(ClaimValue) .join(ClaimName, ClaimValue.claim_name_id == ClaimName.id) .join( global_cv, and_( global_cv.claim_name_id == ClaimName.claim_values_source_id, global_cv.external_id == ClaimValue.external_id, ), ) .filter(ClaimName.claim_values_source_id != None) # noqa ) own_to_global_mapping = {row[0]: (row[1], row[2]) for row in mapping_query} for row in pgdb.session.query(dna_account_claim_table).all(): global_ids = own_to_global_mapping.get(row.claim_value_id) if global_ids: pgdb.session.execute( pgdb.update(dna_account_claim_table) .values( claim_value_id=global_ids[0], claim_name_id=global_ids[1] ) .where(dna_account_claim_table.c.id == row.id) ) cleanup_names_subq = ( pgdb.session.query(ClaimName.id) .filter(ClaimName.claim_values_source_id != None) # noqa .subquery() ) ClaimValue.query.filter( ClaimValue.claim_name_id.in_(cleanup_names_subq) ).delete(synchronize_session="fetch") pgdb.session.commit()