def before_get_object(self, view_kwargs): if view_kwargs.get("id") is not None: try: self.session.query( self.model).filter_by(id=view_kwargs.get("id")).one() except NoResultFound: raise ObjectNotFound({"parameter": "id"}, "{} {} not found".format( self.model.__tablename__, view_kwargs.get("id"))) if view_kwargs.get("order_id") is not None: try: order = self.session.query(Order).filter_by( id=view_kwargs.get("order_id")).one() except NoResultFound: raise ObjectNotFound({"parameter": "order_id"}, "order {} not found".format( view_kwargs.get("order_id"))) else: if order.user is not None: view_kwargs["id"] = order.user_id else: view_kwargs["id"] = None raise ObjectNotFound({"parameter": "order_id"}, "Doesn´t have an related user")
def event_query(self, query_, view_kwargs, event_id='event_id', event_identifier='event_identifier', permission='is_coorganizer_endpoint_related_to_event'): """ Queries the event according to 'event_id' and 'event_identifier' and joins for the query For draft events, if the user is not logged in or does not have required permissions, a 404 is raised :param self: :param event_id: String representing event_id in the view_kwargs :param event_identifier: String representing event_identifier in the view_kwargs :param query_: Query object :param view_kwargs: view_kwargs from the API :param permission: the name of the permission to be applied as a string. Default: is_coorganizer :return: """ if view_kwargs.get(event_id): event = safe_query(self, Event, 'id', view_kwargs[event_id], event_id) if event.state != 'published' and ( 'Authorization' not in request.headers or not has_access(permission, event_id=event.id)): raise ObjectNotFound({'parameter': event_id}, "Event: {} not found".format(view_kwargs[event_id])) query_ = query_.join(Event).filter(Event.id == event.id) elif view_kwargs.get(event_identifier): event = safe_query(self, Event, 'identifier', view_kwargs[event_identifier], event_identifier) if event.state != 'published' and ( 'Authorization' not in request.headers or not has_access(permission, event_id=event.id)): raise ObjectNotFound({'parameter': event_identifier}, "Event: {} not found".format(view_kwargs[event_identifier])) query_ = query_.join(Event).filter(Event.id == event.id) return query_
def validate_satus(self, data, original_data): if 'role' in data and 'role_name' in data: try: role = Role.query.filter_by(id=data['role']).one() except NoResultFound: raise ObjectNotFound({'source': '/data/role'}, "Role not found") if role.name != data['role_name']: raise UnprocessableEntityError( {'pointer': '/data/attributes/role'}, "Role id do not match role name") if 'id' in original_data['data']: try: role_invite = RoleInvite.query.filter_by( id=original_data['data']['id']).one() except NoResultFound: raise ObjectNotFound({'source': '/data/id'}, "Role invite not found") if 'role' not in data: data['role'] = role_invite.role.id if 'role_name' in data: try: role = Role.query.filter_by(id=data['role']).one() except NoResultFound: raise ObjectNotFound({'source': '/data/role'}, "Role not found") if role.name != data['role_name']: raise UnprocessableEntityError( {'pointer': '/data/attributes/role'}, "Role id do not match role name", )
def before_post(self, args, kwargs, data): """ method to add user_id to view_kwargs before post :param args: :param kwargs: :param data: :return: """ require_relationship(['event', 'user'], data) if not has_access('is_coorganizer', event_id=data['event']): event = safe_query(self, Event, 'id', data['event'], 'event_id') if event.state == "draft": raise ObjectNotFound({'parameter': 'event_id'}, "Event: {} not found".format( data['event_id'])) if 'sessions' in data: session_ids = data['sessions'] for session_id in session_ids: if not has_access('is_session_self_submitted', session_id=session_id): raise ObjectNotFound( {'parameter': 'session_id'}, "Session: {} not found".format(session_id))
def before_post(self, args, kwargs, data=None): """ method to add user_id to view_kwargs before post :param args: :param kwargs: :param data: :return: """ require_relationship(['event', 'user'], data) if not has_access('is_coorganizer', event_id=data['event']): event = db.session.query(Event).filter_by(id=data['event']).one() if event.state == "draft": raise ObjectNotFound({'parameter': 'event_id'}, "Event: {} not found".format(data['event_id'])) if get_count(db.session.query(Event).filter_by(id=int(data['event']), is_sessions_speakers_enabled=False)) > 0: raise ForbiddenException({'pointer': ''}, "Speakers are disabled for this Event") if get_count(db.session.query(Speaker).filter_by(event_id=int(data['event']), email=data['email'], deleted_at=None)) > 0: raise ForbiddenException({'pointer': ''}, 'Speaker with this Email ID already exists') if 'sessions' in data: session_ids = data['sessions'] for session_id in session_ids: if not has_access('is_session_self_submitted', session_id=session_id): raise ObjectNotFound({'parameter': 'session_id'}, "Session: {} not found".format(session_id))
def before_get(self, args, kwargs): """ before get method of access code details. Check for permissions on the basis of kwargs. :param args: :param kwargs: :return: """ # Any registered user can fetch access code details using the code. if kwargs.get('code'): access = db.session.query(AccessCode).filter_by( code=kwargs.get('code')).first() if access: kwargs['id'] = access.id else: raise ObjectNotFound({'parameter': '{code}'}, "Access Code: not found") return # Co-organizer or the admin can fetch access code details using the id. if kwargs.get('id'): access = db.session.query(AccessCode).filter_by( id=kwargs.get('id')).one() if not access: raise ObjectNotFound({'parameter': '{id}'}, "Access Code: not found") if not has_access('is_coorganizer', event_id=access.event_id): raise UnprocessableEntity({'source': ''}, "Please verify your permission")
def before_get_object(self, view_kwargs): if view_kwargs.get('comments_id') is not None: try: comment = self.session.query(models.Comment).filter_by( id=view_kwargs['comments_id']).one() except NoResultFound: raise ObjectNotFound({'parameter': 'comments_id'}, "Comment: {} not found".format( view_kwargs['comments_id'])) else: if comment.user is not None: view_kwargs['id'] = comment.user.id else: view_kwargs['id'] = None if view_kwargs.get('posts_id') is not None: try: post = self.session.query(models.Comment).filter_by( id=view_kwargs['posts_id']).one() except NoResultFound: raise ObjectNotFound({'parameter': 'posts_id'}, "Post: {} not found".format( view_kwargs['posts_id'])) else: if post.user is not None: view_kwargs['id'] = post.user.id else: view_kwargs['id'] = None
def before_get_object(self, view_kwargs): """ before get method to get the resource id for fetching details :param view_kwargs: :return: """ if view_kwargs.get('event_identifier'): try: event = (self.session.query(Event).filter_by( identifier=view_kwargs['event_identifier']).one()) except NoResultFound: raise ObjectNotFound( {'parameter': 'event_identifier'}, "Event: {} not found".format( view_kwargs['event_identifier']), ) else: view_kwargs['event_id'] = event.id if view_kwargs.get('event_id'): try: speakers_call = (self.session.query(SpeakersCall).filter_by( event_id=view_kwargs['event_id']).one()) except NoResultFound: raise ObjectNotFound({'parameter': 'event_identifier'}, "Object: not found") view_kwargs['id'] = speakers_call.id
def before_get_object(self, view_kwargs): if view_kwargs.get("id") is not None: print("idddddddddddddd") try: self.session.query( self.model).filter_by(id=view_kwargs["id"]).one() except NoResultFound: raise ObjectNotFound({"parameter": "id"}, "{} {} not found".format( self.model.__tablename__, view_kwargs.get("id"))) if view_kwargs.get("article_id") is not None: try: art = self.session.query(Article).filter_by( id=view_kwargs["article_id"]).one() except NoResultFound: raise ObjectNotFound({"parameter": "article_id"}, "Article {} not found".format( view_kwargs.get("article_id"))) else: if art.category is not None: print("AQEUIIII") view_kwargs["id"] = art.CategoryId else: raise ObjectNotFound({"parameter": "id"}, "Doesnt have any Category related")
def before_post(self, args, kwargs, data=None): """ method to add user_id to view_kwargs before post :param args: :param kwargs: :param data: :return: """ data['user'] = current_user.id require_relationship(['event', 'user'], data) if not has_access('is_coorganizer', event_id=data['event']): event = db.session.query(Event).filter_by(id=data['event']).one() if event.state == "draft": raise ObjectNotFound( {'parameter': 'event_id'}, "Event: {} not found".format(data['event']), ) if (get_count( db.session.query(Event).filter_by( id=int(data['event']), is_sessions_speakers_enabled=False)) > 0): raise ForbiddenError({'pointer': ''}, "Speakers are disabled for this Event") if (not data.get('is_email_overridden') and get_count( db.session.query(Speaker).filter_by(event_id=int( data['event']), email=data['email'], deleted_at=None)) > 0): raise ForbiddenError({'pointer': ''}, 'Speaker with this Email ID already exists') if data.get('is_email_overridden') and not has_access( 'is_organizer', event_id=data['event']): raise ForbiddenError( {'pointer': 'data/attributes/is_email_overridden'}, 'Organizer access required to override email', ) if (data.get('is_email_overridden') and has_access('is_organizer', event_id=data['event']) and not data.get('email')): data['email'] = current_user.email if 'sessions' in data: session_ids = data['sessions'] for session_id in session_ids: if not has_access('is_session_self_submitted', session_id=session_id): raise ObjectNotFound( {'parameter': 'session_id'}, f"Session: {session_id} not found", ) data[ 'complex_field_values'] = validate_custom_form_constraints_request( 'speaker', self.schema, Speaker(event_id=data['event']), data)
def get_hv_object(self, hv_id): if hv_id not in self.hypervisors: raise ObjectNotFound('no hypervisor with id: ' + str(hv_id)) o = None with self.mutex: o = self.hypervisors[hv_id]['model'] return o
def update_object(self, obj, data, view_kwargs): """Update an object through sqlalchemy :param DeclarativeMeta obj: an object from sqlalchemy :param dict data: the data validated by marshmallow :param dict view_kwargs: kwargs from the resource view :return boolean: True if object have changed else False """ if obj is None: url_field = getattr(self, 'url_field', 'id') filter_value = view_kwargs[url_field] raise ObjectNotFound('{}: {} not found'.format( self.model.__name__, filter_value), source={'parameter': url_field}) self.before_update_object(obj, data, view_kwargs) relationship_fields = get_relationships(self.resource.schema, model_field=True) for key, value in data.items(): if hasattr(obj, key) and key not in relationship_fields: setattr(obj, key, value) self.apply_relationships(data, obj) try: self.session.commit() except Exception as e: self.session.rollback() raise JsonApiException("Update object error: " + str(e), source={'pointer': '/data'}) self.after_update_object(obj, data, view_kwargs)
def before_get(self, args, kwargs): """ before get method to get the resource id for fetching details :param args: :param kwargs: :return: """ if 'id' in kwargs: try: tax = Tax.query.filter_by(id=kwargs['id']).one() except NoResultFound: raise ObjectNotFound( {'parameter': 'id'}, "Tax: Not found for id {}".format(id) ) if 'Authorization' in request.headers and has_access( 'is_coorganizer', event_id=tax.event_id ): self.schema = TaxSchema else: self.schema = TaxSchemaPublic else: if 'Authorization' in request.headers and has_access( 'is_coorganizer', event_id=kwargs['event_id'] ): self.schema = TaxSchema else: self.schema = TaxSchemaPublic
def get_object(self, **view_kwargs): """Retrieve an object through sqlalchemy :params dict view_kwargs: kwargs from the resource view :return DeclarativeMeta: an object from sqlalchemy """ id_field = getattr(self, 'id_field', inspect(self.model).primary_key[0].name) try: filter_field = getattr(self.model, id_field) except Exception: raise Exception( "{} has no attribut {}".format(self.model.__name__), id_field) url_field = getattr(self, 'url_field', 'id') filter_value = view_kwargs[url_field] try: obj = self.session.query( self.model).filter(filter_field == filter_value).one() except NoResultFound: raise ObjectNotFound( '', "Could not find {}.{}={} object".format( self.model.__name__, id_field, filter_value)) return obj
def query(self, view_kwargs): ''' Constructs the base query Args: view_kwargs (dict): kwargs from the resource view Returns: A query I presume. ''' id_ = view_kwargs.get('id') type_ = view_kwargs.get('type') query_ = self.session.query(self.model) if type_: model = get_class_by_tablename(type_[:-1]) try: self.session.query(model).filter_by(id=id_).one() except NoResultFound: raise ObjectNotFound({'parameter': 'id'}, "{}: {} not found".format(type_, id_)) else: subq = self.session.query(model).subquery() attr_name = self.attrs.get(type_, type_) query_ = query_.join(subq, attr_name, aliased=True).filter(model.id == id_) return query_
def delete_relationship(self, json_data, relationship_field, related_id_field, view_kwargs): """Delete a relationship :param dict json_data: the request params :param str relationship_field: the model attribute used for relationship :param str related_id_field: the identifier field of the related model :param dict view_kwargs: kwargs from the resource view """ self.before_delete_relationship(json_data, relationship_field, related_id_field, view_kwargs) obj = self.get_object(view_kwargs) if obj is None: url_field = getattr(self, 'url_field', 'id') filter_value = view_kwargs[url_field] raise ObjectNotFound('{}: {} not found'.format( self.model.__name__, filter_value), source={'parameter': url_field}) if not hasattr(obj, relationship_field): raise RelationNotFound("{} has no attribute {}".format( obj.__class__.__name__, relationship_field)) related_model = getattr(obj.__class__, relationship_field).property.mapper.class_ updated = False if isinstance(json_data['data'], list): obj_ids = { str(getattr(obj__, related_id_field)) for obj__ in getattr(obj, relationship_field) } for obj_ in json_data['data']: if obj_['id'] in obj_ids: getattr(obj, relationship_field).remove( self.get_related_object(related_model, related_id_field, obj_)) updated = True else: setattr(obj, relationship_field, None) updated = True try: self.session.commit() except JsonApiException as e: self.session.rollback() raise e except Exception as e: self.session.rollback() raise JsonApiException("Delete relationship error: " + str(e)) self.after_delete_relationship(obj, updated, json_data, relationship_field, related_id_field, view_kwargs) return obj, updated
def validate_ticket_holders(ticket_holder_ids): # pytype: disable=attribute-error ticket_holders = (TicketHolder.query.filter_by(deleted_at=None).filter( TicketHolder.id.in_(ticket_holder_ids)).all()) # pytype: enable=attribute-error if len(ticket_holders) != len(ticket_holder_ids): logger.warning("Ticket Holders not found in", extra=dict(ticket_holder_ids=ticket_holder_ids)) raise ObjectNotFound( {'pointer': '/data/relationships/attendees'}, "Some attendee among ids {} do not exist".format( str(ticket_holder_ids)), ) for ticket_holder in ticket_holders: # Ensuring that the attendee exists and doesn't have an associated order. if ticket_holder.order_id: logger.warning( "Order already exists for attendee", extra=dict(attendee_id=ticket_holder.id), ) raise ConflictError( {'pointer': '/data/relationships/attendees'}, "Order already exists for attendee with id {}".format( str(ticket_holder.id)), ) return ticket_holders
def get_relationship(self, relationship_field, related_type_, related_id_field, view_kwargs): """Get a relationship :param str relationship_field: the model attribute used for relationship :param str related_type_: the related resource type :param str related_id_field: the identifier field of the related model :param dict view_kwargs: kwargs from the resource view :return tuple: the object and related object(s) """ self.before_get_relationship(relationship_field, related_type_, related_id_field, view_kwargs) obj = self.get_object(view_kwargs) if obj is None: url_field = getattr(self, 'url_field', 'id') filter_value = view_kwargs[url_field] raise ObjectNotFound('{}: {} not found'.format(self.model.__name__, filter_value), source={'parameter': url_field}) if not hasattr(obj, relationship_field): raise RelationNotFound("{} has no attribute {}".format(obj.__class__.__name__, relationship_field)) related_objects = getattr(obj, relationship_field) if related_objects is None: return obj, related_objects self.after_get_relationship(obj, related_objects, relationship_field, related_type_, related_id_field, view_kwargs) if isinstance(related_objects, InstrumentedList): return obj,\ [{'type': related_type_, 'id': getattr(obj_, related_id_field)} for obj_ in related_objects] else: return obj, {'type': related_type_, 'id': getattr(related_objects, related_id_field)}
def delete_object(self, obj, view_kwargs): """Delete an object through sqlalchemy :param DeclarativeMeta item: an item from sqlalchemy :param dict view_kwargs: kwargs from the resource view """ if obj is None: url_field = getattr(self, 'url_field', 'id') filter_value = view_kwargs[url_field] raise ObjectNotFound('{}: {} not found'.format( self.model.__name__, filter_value), source={'parameter': url_field}) self.before_delete_object(obj, view_kwargs) self.session.delete(obj) try: self.session.commit() except JsonApiException as e: self.session.rollback() raise e except Exception as e: self.session.rollback() raise JsonApiException("Delete object error: " + str(e)) self.after_delete_object(obj, view_kwargs)
def safe_query_without_soft_deleted_entries(self, model, column_name, value, parameter_name): """ Wrapper query to properly raise exception after filtering the soft deleted entries :param self: :param model: db Model to be queried :param column_name: name of the column to be queried for the given value :param value: value to be queried against the given column name, e.g view_kwargs['event_id'] :param parameter_name: Name of parameter to be printed in json-api error message eg 'event_id' :return: """ try: if hasattr(model, 'deleted_at'): record = (self.session.query(model).filter( getattr(model, column_name) == value).filter_by( deleted_at=None).one()) else: record = (self.session.query(model).filter( getattr(model, column_name) == value).one()) except NoResultFound: raise ObjectNotFound( {'parameter': '{}'.format(parameter_name)}, "{}: {} not found".format(model.__name__, value), ) else: return record
def send_receipt(): """ Send receipts to attendees related to the provided order. :return: """ order_identifier = request.json.get('order-identifier') if order_identifier: try: order = db.session.query(Order).filter_by( identifier=order_identifier).one() except NoResultFound: raise ObjectNotFound({'parameter': '{identifier}'}, "Order not found") if (order.user_id != current_user.id) and (not has_access( 'is_registrar', event_id=order.event_id)): abort( make_response( jsonify( error= "You need to be the event organizer or order buyer to send receipts." ), 403)) elif order.status != 'completed': abort( make_response( jsonify( error="Cannot send receipt for an incomplete order"), 409)) else: send_email_to_attendees(order, current_user.id) return jsonify(message="receipt sent to attendees") else: abort(make_response(jsonify(error="Order identifier missing"), 422))
def decide_schema(self, json_data): """To decide discount code schema based on posted data. :param json_data: :return:""" used_for = json_data['data']['attributes'].get('used-for') try: discount = ( db.session.query(DiscountCode) .filter_by(id=int(json_data['data']['id'])) .one() ) except NoResultFound: raise ObjectNotFound({'parameter': '{id}'}, "DiscountCode: not found") if not used_for: used_for = discount.used_for elif used_for != discount.used_for: raise ConflictError( {'pointer': '/data/attributes/used-for'}, "Cannot modify discount code usage type", ) if used_for == 'ticket': self.schema = DiscountCodeSchemaTicket elif used_for == 'event': self.schema = DiscountCodeSchemaEvent
def event_invoices(invoice_identifier): if not current_user: raise ForbiddenError({'source': ''}, 'Authentication Required to access Invoice') try: event_invoice = EventInvoice.query.filter_by( identifier=invoice_identifier).first() event_id = event_invoice.event_id except NoResultFound: raise NotFoundError({'source': ''}, 'Event Invoice not found') if not current_user.is_organizer(event_id) and not current_user.is_staff: raise ForbiddenError({'source': ''}, 'Unauthorized Access') key = UPLOAD_PATHS['pdf']['event_invoices'].format( identifier=invoice_identifier) file_path = ( '../generated/invoices/{}/{}/'.format(key, generate_hash(key)) + invoice_identifier + '.pdf') try: return return_file('event-invoice', file_path, invoice_identifier) except FileNotFoundError: raise ObjectNotFound( {'source': ''}, "The Event Invoice isn't available at the moment. \ Invoices are usually issued on the 1st of every month", )
def validate_date(self, data, original_data): if 'id' in original_data['data']: try: event = Event.query.filter_by( id=original_data['data']['id']).one() except NoResultFound: raise ObjectNotFound({'source': 'data/id'}, "Event id not found") if 'starts_at' not in data: data['starts_at'] = event.starts_at if 'ends_at' not in data: data['ends_at'] = event.ends_at if 'starts_at' not in data or 'ends_at' not in data: raise UnprocessableEntity( {'pointer': '/data/attributes/date'}, "enter required fields starts-at/ends-at") if data['starts_at'] >= data['ends_at']: raise UnprocessableEntity({'pointer': '/data/attributes/ends-at'}, "ends-at should be after starts-at") if datetime.timestamp(data['starts_at']) <= datetime.timestamp( datetime.now()): raise UnprocessableEntity( {'pointer': '/data/attributes/starts-at'}, "starts-at should be after current date-time")
def before_post(self, args, kwargs, data): """ before post method to check for required relationship and proper permission :param args: :param kwargs: :param data: :return: """ require_relationship(['event'], data) if not has_access('is_coorganizer', event_id=data['event']): raise ObjectNotFound( {'parameter': 'event_id'}, "Event: {} not found".format(data['event']) ) if ( get_count( db.session.query(Ticket.id).filter_by( name=data['name'], event_id=int(data['event']), deleted_at=None ) ) > 0 ): raise ConflictError( {'pointer': '/data/attributes/name'}, "Ticket already exists" )
def before_create_object(self, data, view_kwargs): """Prior to creating a new item, check all is OK and insert the user_id of the current user into the request, so that the foreign key for user_id is correctly s0tored with created item. Also stores the category_id of the request URL into the data storage used to set the foreign key of the item pointing to the category. """ # pylint: disable=no-self-use # POST /api/v1/categories/<int:category_id>/items category_id = view_kwargs.get('category_id') if ('name' not in data and 'description' not in data): raise BadRequest('Must include id (of category), name and ' 'description fields') try: category = Category.query.filter_by(id=category_id).one() except NoResultFound: raise ObjectNotFound({'parameter': 'category_id'}, "Category with id: {} not found".format( data['category_id'])) # set the foreign key to the logged in user data['user_id'] = g.current_user.id # set the foreign key for category data['category_id'] = category.id
def validate_quantity(self, data, original_data): if 'id' in original_data['data']: try: discount_code = DiscountCode.query.filter_by( id=original_data['data']['id']).one() except NoResultFound: raise ObjectNotFound({'parameter': '{code}'}, "DiscountCode: not found") if 'min_quantity' not in data: data['min_quantity'] = discount_code.min_quantity if 'max_quantity' not in data: data['max_quantity'] = discount_code.max_quantity if 'tickets_number' not in data: data['tickets_number'] = discount_code.tickets_number DiscountCodeSchemaTicket.quantity_validation_helper(data) if 'tickets_number' in data and 'max_quantity' in data: if data['tickets_number'] < data['max_quantity']: raise UnprocessableEntity( {'pointer': '/data/attributes/tickets-number'}, "tickets-number should be greater than max-quantity")
def before_get_object(self, view_kwargs): if view_kwargs.get('id') is not None: try: source = self.session.query(Source).filter_by(id=view_kwargs['id']).one() except NoResultFound: raise ObjectNotFound({'parameter': 'id'}, "Source: {} not found".format(view_kwargs['id']))
def query(self, view_kwargs): query_ = self.session.query(Order_Article) if view_kwargs.get("order_id") is not None: arg = "order_id" model = Order elif view_kwargs.get("article_id") is not None: arg = "article_id" model = Article else: arg = "" model = None if view_kwargs.get(arg) is not None: try: self.session.query(model).filter_by(id=view_kwargs[arg]).one() except NoResultFound: raise ObjectNotFound({'parameter': arg}, "{}:{} not found".format( model.__tablename__, view_kwargs.get(arg))) else: query_ = query_.join(model).filter( model.id == view_kwargs.get(arg)) # retornando query de los usuarios relcionados con el rol especifiado por el id return query_
def safe_query_without_soft_deleted_entries(model, column_name, value, parameter_name, filter_deleted=True): """ Wrapper query to properly raise exception after filtering the soft deleted entries :param model: db Model to be queried :param column_name: name of the column to be queried for the given value :param value: value to be queried against the given column name, e.g view_kwargs['event_id'] :param parameter_name: Name of parameter to be printed in json-api error message eg 'event_id' :param filter_deleted: Deleted records are filtered if set to true :return: """ try: record = model.query.filter(getattr(model, column_name) == value) if filter_deleted and hasattr(model, 'deleted_at'): record = record.filter_by(deleted_at=None) record = record.one() except NoResultFound: raise ObjectNotFound( {'parameter': f'{parameter_name}'}, f"{model.__name__}: {value} not found", ) else: return record