"""Blueprints for abacus schedule.""" from abacus_common_logic.views.create_view import CreateView from abacus_common_logic.views.item_view import ItemView from flask import Blueprint, request from owsrequest import flask_request from owsresponse import response from owsresponse.adaptors.flask import flaskify from abacus_schedule.constants import error from abacus_schedule.logic import schedule as logic from abacus_schedule.models.schedule import Schedule from abacus_schedule.schemas.schedule import ScheduleDetailSchema from abacus_schedule.utils import authorization schedule_api = Blueprint('schedule_api', __name__) class ScheduleCreateView(CreateView): """Handles account creation.""" post_schema = ScheduleDetailSchema(exclude=['schedule_id']) def create_handler(self, **params): """Create a schedule.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message=error.ERROR_MESSAGE_FORBIDDEN_USER, status=403, ) ) return logic.create_schedule(**params) class ScheduleItemView(ItemView): """View for fetching a abacus state by ID.""" model_class = Schedule object_detail_schema = ScheduleDetailSchema() put_schema = ScheduleDetailSchema( only=('schedule_name', 'conditions'), partial=True ) def get(self, object_id, **kwargs): """Find schedule by its id or return an error.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: # Currently, we're treating this resource type as all-or-nothing # permissions-wise, so resource id doesn't matter. Ideally, would be # able to tie back to contract -> account and authorize on that. authorized = authorization.pdp_authorize_resource( resource_id=object_id, resource_type='abacus_schedule', ) if not authorized: return flaskify( response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message=error.ERROR_MESSAGE_FORBIDDEN_USER, status=403, ) ) return super().get(object_id, **kwargs) def update_handler(self, obj, **params): """Handle schedule updates.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message=error.ERROR_MESSAGE_FORBIDDEN_USER, status=403, ) ) return logic.update_schedule(obj, **params) schedule_api.add_url_rule( '/schedule/', methods=['GET', 'PUT'], view_func=ScheduleItemView.as_view('schedule'), ) schedule_api.add_url_rule( '/schedule', methods=['POST'], view_func=ScheduleCreateView.as_view('create_schedule'), ) @schedule_api.route( '/schedules//', methods=['GET'] ) def get_schedules_by_target(target_type, target_id): """Endpoint to GET schedules for a given target type and id.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: # Currently, we're treating this resource type as all-or-nothing # permissions-wise, so resource id doesn't matter. Ideally, would be # able to tie back to contract -> account and authorize on that. authorized = authorization.pdp_authorize_resource( resource_id=f'target_{target_type}_{target_id}', resource_type='abacus_schedule', ) if not authorized: return flaskify( response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message=error.ERROR_MESSAGE_FORBIDDEN_USER, status=403, ) ) request_params = request.args return flaskify( logic.get_schedules_by_target(target_type, target_id, request_params) )