"""Application and role related handlers.""" from connector_neo4j import Neo4jSession from flask import request from owsresponse import response from owsresponse.adaptors.flask import flaskify from account.api import app from account.constants import error from account.constants.connectors import NEO4J_DATABASE_NAME from account.constants.constants import ALLOWED_PARENT_COMPANY_UUIDS, SME_PARENT_COMPANY_UUID from account.constants.tenants import TenantType from account.logic.application import ( application as app_logic, collaborator as collaborator_app_logic, label_participant as label_participant_logic, subaccount as subaccount_app_logic, vendor as vendor_app_logic, ) from account.models import application as app_model from account.utils import authorization, handler_util from account.utils.api_utils import jwt_check, validate_request_data from account.validation.schemas.dataloader import ( SubaccountsDataloader, VendorsDataloader, ) @app.route('/vendor//applications', methods=['GET']) @jwt_check @handler_util.check_admin_access(tenant_type=TenantType.ACCOUNT, tenant_uuid_key='vendor_uuid') def get_vendor_applications(vendor_uuid): """Get applications and roles for a Vendor.""" return flaskify(vendor_app_logic.get_vendor_applications(vendor_uuid)) @app.route('/vendors/applications/dataloader', methods=['POST']) @jwt_check @validate_request_data(VendorsDataloader()) @handler_util.check_bulk_admin_access(tenant_type=TenantType.ACCOUNT) def get_bulk_vendor_applications(deserialize_schema): """Get applications and roles for multiple Vendors.""" vendor_uuids = deserialize_schema['vendor_uuids'] return flaskify(response.Response(vendor_app_logic.get_bulk_vendor_applications(vendor_uuids))) @app.route('/subaccount//applications', methods=['GET']) @jwt_check @handler_util.check_admin_access( tenant_type=TenantType.SUBACCOUNT, tenant_uuid_key='subaccount_uuid' ) def get_subaccount_applications(subaccount_uuid): """Get applications and roles for a Subaccount.""" return flaskify(subaccount_app_logic.get_subaccount_applications(subaccount_uuid)) @app.route('/subaccounts/applications/dataloader', methods=['POST']) @jwt_check @validate_request_data(SubaccountsDataloader()) @handler_util.check_bulk_admin_access(tenant_type=TenantType.SUBACCOUNT) def get_bulk_subaccount_applications(deserialize_schema): """Get applications and roles for multiple Subaccounts.""" subaccount_uuids = deserialize_schema['subaccount_uuids'] return flaskify( response.Response(subaccount_app_logic.get_bulk_subaccount_applications(subaccount_uuids)) ) @app.route('/collaborator//applications', methods=['GET']) @jwt_check @Neo4jSession(use_v2=True, database=NEO4J_DATABASE_NAME) @handler_util.check_admin_access( tenant_type=TenantType.COLLABORATOR, tenant_uuid_key='collaborator_uuid' ) def get_collaborator_applications(collaborator_uuid): """Get applications and roles for a Collaborator.""" return flaskify(collaborator_app_logic.get_collaborator_applications(collaborator_uuid)) @app.route('/label-participant//applications', methods=['GET']) @jwt_check @Neo4jSession(use_v2=True, database=NEO4J_DATABASE_NAME) @handler_util.check_admin_access( tenant_type=TenantType.LABEL_PARTICIPANT, tenant_uuid_key='lp_uuid' ) def get_label_participant_applications(lp_uuid): """Get applications and roles for a label participant.""" applications = label_participant_logic.get_lp_applications(lp_uuid) return flaskify(response.Response({'applications': applications})) @app.route('/applications/dataloader', methods=['POST']) def get_applications_by_ids(): """Endpoint to get applications by ids.""" application_ids = request.get_json() return flaskify(app_logic.get_applications_by_ids(application_ids)) @app.route('/roles/dataloader', methods=['POST']) def get_roles_by_ids(): """Endpoint to get roles by ids.""" role_ids = request.get_json() return flaskify(app_logic.get_roles_by_ids(role_ids)) @app.route('/internal/parent_company//applications', methods=['GET']) @jwt_check def get_parent_company_applications(parent_company_uuid: str): """Get applications and default roles for a parent company. This endpoint is used by the SEAT employee invitation flow to display available applications and roles when configuring permissions for a new employee. Args: parent_company_uuid: UUID of the parent company (must be SME or The Orchard). Returns: Flask.response: JSON with list of applications and their default roles. - 200 OK: Returns applications list - 400 Bad Request: UUID not in allowed list - 403 Forbidden: User lacks seat_can_administer_users role """ # Authorization check via PDP for seat_can_administer_users role if not authorization.pdp_authorize_manage_employee(): return flaskify( response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Forbidden', status=403, ) ) # Validate UUID is in allowed list if parent_company_uuid not in ALLOWED_PARENT_COMPANY_UUIDS: return flaskify( response.create_error_response( code=error.ERROR_CODE_INVALID_INPUT, message='Invalid parent company UUID', status=400, ) ) url_domain = 'sme' if parent_company_uuid == SME_PARENT_COMPANY_UUID else 'theorchard' # Return hardcoded applications for MVP applications = [ { 'application_id': app_model.INSIGHTS_APP, 'roles': [app_model.INSIGHTS_BASE_ROLE], 'url': f'https://insights.{url_domain}.com', }, { 'application_id': app_model.SETTINGS_APP, 'roles': [app_model.SETTINGS_BASE_ROLE], 'url': f'https://settings.{url_domain}.com', }, ] return flaskify(response.Response({'applications': applications}))