def __init__(self, product, *args, **kwargs): super(GiftCardForm, self).__init__(*args, **kwargs) Product = Pool().get('product.product') if not isinstance(product, Product): abort(400) try: self.gc_product, = Product.search([ ('id', '=', product.id), ('is_gift_card', '=', True) ], limit=1) except ValueError as e: e.message = 'Expected Gift Card, Got %s' % (product.rec_name) raise self.fill_choices() if self.gc_product.gift_card_delivery_mode in ['virtual', 'combined']: self.recipient_email.validators = [ validators.DataRequired(), validators.Email() ] else: self.recipient_email.validators = [ validators.Optional(), validators.Email() ]
def render(cls, uri, page=1): """ Renders the category """ Article = Pool().get('nereid.cms.article') # Find in cache or load from DB try: category, = cls.search([('unique_name', '=', uri)]) except ValueError: abort(404) order = [] if category.sort_order == 'recent_first': order.append(('write_date', 'DESC')) elif category.sort_order == 'older_first': order.append(('write_date', 'ASC')) elif category.sort_order == 'sequence': order.append(('sequence', 'ASC')) articles = Pagination( Article, [ ('categories', '=', category.id), ('state', '=', 'published') ], page, category.articles_per_page, order=order ) return render_template( category.template, category=category, articles=articles)
def process(cls, sale, payment_method_id): """Begins the payment processing. Returns a response object if a redirect to third party website is required, else processes the payment. :param sale: Browse Record of the Sale :param payment_method_id: ID of payment method """ Sale = Pool().get('sale.sale') try_to_authorize = ( request.nereid_website.payment_mode == 'auth_if_available') payment_method = cls(payment_method_id) allowed_gateways = cls._get_available_gateways( sale.invoice_address.country) if payment_method not in allowed_gateways: current_app.logger.error("Payment method %s is not valid" % payment_method.name) abort(403) payment_method_obj = Pool().get(payment_method.model.model) Sale.write([sale], {'payment_method': payment_method.id}) if try_to_authorize and hasattr(payment_method_obj, 'authorize'): return payment_method_obj.authorize(sale) else: return payment_method_obj.capture(sale)
def start_session(cls): ''' POST: Start chat session with another user. :args user: User Id of nereid user. :return: JSON as { thread_id: uuid, members: Serialized members list. } ''' NereidUser = Pool().get('nereid.user') form = NewChatForm() if not form.validate_on_submit(): return jsonify(errors=form.errors), 400 chat_with = NereidUser(form.user.data) if not request.nereid_user.can_chat(chat_with): abort(403, "You can only talk to friends") chat = cls.get_or_create_room( request.nereid_user.id, chat_with.id ) return jsonify({ 'thread_id': chat.thread, 'members': map( lambda m: m.user.serialize(), chat.members ) })
def register_device(self, device, pass_type=None, version=None): """ Register the device against this pass :pass_type: The pass_type is ignored because serial number sent as active_id is unique enough to identify the pass """ Registration = Pool().get('nereid.passbook.registration') self.check_authorization() push_token = request.json['pushToken'] # Check if a registration already exists regns = Registration.search([('pass_', '=', self.id), ('device_library_identifier', '=', device) ]) if regns: if request.method == 'DELETE': Registration.delete(regns) return '', 200 if request.method == 'DELETE': # Requested deletion of a registration that does not exist abort(404) # No regn. Create a new registration regn = Registration( pass_=self, device_library_identifier=device, push_token=push_token, ) regn.save() return '', 201
def get_available_gateways(cls): """Return the JSONified list of payment gateways available This is a XHR only method If type is specified as address then an address lookup is done """ Address = Pool().get('party.address') value = request.args.get('value', 0, type=int) if request.values.get('type') == 'address': # Address lookup only when logged in if request.is_guest_user: abort(403) # If not validated as user's address this could lead to # exploitation by ID if value not in [ a.id for a in request.nereid_user.party.addresses ]: abort(403) address = Address(value) value = address.country.id rv = [{ 'id': g.id, 'name': g.name, 'image': g.get_image(), } for g in cls._get_available_gateways(value)] return jsonify(result=rv)
def start_session(cls): ''' POST: Start chat session with another user. :args user: User Id of nereid user. :return: JSON as { thread_id: uuid, members: Serialized members list. } ''' NereidUser = Pool().get('nereid.user') form = NewChatForm() if not form.validate_on_submit(): return jsonify(errors=form.errors), 400 chat_with = NereidUser(form.user.data) if not request.nereid_user.can_chat(chat_with): abort(403, "You can only talk to friends") chat = cls.get_or_create_room(request.nereid_user.id, chat_with.id) return jsonify({ 'thread_id': chat.thread, 'members': map(lambda m: m.user.serialize(), chat.members) })
def delete_from_cart(cls, line): """ Delete a line from the cart. The required argument in POST is: line_id : ID of the line Response: 'OK' if X-HTTPRequest else redirect to shopping cart """ SaleLine = Pool().get('sale.line') cart = cls.open_cart() if not cart.sale: abort(404) try: sale_line, = SaleLine.search([ ('id', '=', line), ('sale', '=', cart.sale.id), ]) except ValueError: message = 'Looks like the item is already deleted.' else: SaleLine.delete([sale_line]) message = 'The order item has been successfully removed.' cart_updated.send(cart) flash(_(message)) if request.is_xhr: return jsonify(message=message) return redirect(url_for('nereid.cart.view_cart'))
def edit_post(self): """ Edit an existing post """ if self.nereid_user != request.nereid_user: abort(404) # Search for a post with same uri post_form = BlogPostForm(request.form, obj=self) with Transaction().set_context(blog_id=self.id): if request.method == 'POST' and post_form.validate(): self.title = post_form.title.data self.content = post_form.content.data self.allow_guest_comments = post_form.allow_guest_comments.data self.save() flash('Your post has been updated.') if request.is_xhr: return jsonify(success=True, item=self.serialize()) return redirect(url_for( 'blog.post.render', user_id=self.nereid_user.id, uri=self.uri )) if request.is_xhr: return jsonify( success=request.method != 'POST', # False for POST, else True errors=post_form.errors or None, ) return render_template( 'blog_post_edit.jinja', form=post_form, post=self )
def render(self, slug=None, page=1): """ Renders a page of products in the tree and all of its branches :param slug: slug of the browse node to be shown :param page: page of the products to be displayed """ Product = Pool().get('product.product') try: self.slug except UserError: abort(404) if self.type_ != 'catalog': # Display only catalog nodes abort(403) products = Pagination(Product, [ ('displayed_on_eshop', '=', True), ('nodes.left', '>=', self.left), ('nodes.right', '<=', self.right), ('template.active', '=', True), ], page=page, per_page=self.products_per_page) return render_template( 'catalog/node.html', products=products, node=self )
def delete_from_cart(cls, line): """ Delete a line from the cart. The required argument in POST is: line_id : ID of the line Response: 'OK' if X-HTTPRequest else redirect to shopping cart """ SaleLine = Pool().get('sale.line') cart = cls.open_cart() if not cart.sale: abort(404) try: sale_line, = SaleLine.search([ ('id', '=', line), ('sale', '=', cart.sale.id), ]) except ValueError: message = 'Looks like the item is already deleted.' else: SaleLine.delete([sale_line]) message = 'The order item has been successfully removed.' flash(_(message)) if request.is_xhr: return jsonify(message=message) return redirect(url_for('nereid.cart.view_cart'))
def render(cls, user_id, uri): "Render the blog post" NereidUser = Pool().get('nereid.user') if 're_captcha_public' in CONFIG.options and request.is_guest_user: comment_form = GuestCommentForm( captcha={'ip_address': request.remote_addr}) else: comment_form = PostCommentForm() user = NereidUser(user_id) posts = cls.search([ ('nereid_user', '=', user.id), ('uri', '=', uri), ]) if not posts: abort(404) # if only one post is found then it is rendered and # if more than one are found then the first one is rendered post = posts[0] if not (post.state == 'Published' or request.nereid_user == post.nereid_user): abort(403) if request.is_xhr: return jsonify(post.serialize()) return render_template('blog_post.jinja', post=post, comment_form=comment_form, poster=user)
def get_available_gateways(cls): """Return the JSONified list of payment gateways available This is a XHR only method If type is specified as address then an address lookup is done """ Address = Pool().get('party.address') value = request.args.get('value', 0, type=int) if request.values.get('type') == 'address': # Address lookup only when logged in if request.is_guest_user: abort(403) # If not validated as user's address this could lead to # exploitation by ID if value not in [a.id for a in request.nereid_user.party.addresses]: abort(403) address = Address(value) value = address.country.id rv = [{ 'id': g.id, 'name': g.name, 'image': g.get_image(), } for g in cls._get_available_gateways(value)] return jsonify(result=rv)
def render_comments(self): """ Render comments GET: Return json of all the comments of this post. POST: Create new comment for this post. """ if self.state != 'Published': abort(404) # Add re_captcha if the configuration has such an option and user # is guest if 're_captcha_public' in CONFIG.options and request.is_guest_user: comment_form = GuestCommentForm( request.form, captcha={'ip_address': request.remote_addr} ) else: comment_form = PostCommentForm(request.form) if request.method == 'GET': if self.nereid_user == request.nereid_user: return jsonify(comments=[ comment.serialize() for comment in self.comments ]) return jsonify(comments=[ comment.serialize() for comment in self.comments if not comment.is_spam ]) # If post does not allow guest comments, # then dont allow guest user to comment if not self.allow_guest_comments and request.is_guest_user: flash('Guests are not allowed to write comments') if request.is_xhr: return jsonify( success=False, errors=['Guests are not allowed to write comments'] ) return redirect(url_for( 'blog.post.render', user_id=self.nereid_user.id, uri=self.uri )) if request.method == 'POST' and comment_form.validate(): self.write([self], { 'comments': [('create', [{ 'nereid_user': current_user.id if not current_user.is_anonymous() else None, 'name': current_user.display_name if not current_user.is_anonymous() else comment_form.name.data, 'content': comment_form.content.data, }])] }) if request.is_xhr: return jsonify(success=True) if comment_form.validate() \ else jsonify(success=False, errors=comment_form.errors) return redirect(url_for( 'blog.post.render', user_id=self.nereid_user.id, uri=self.uri ))
def edit_post(self): """ Edit an existing post """ if self.nereid_user != request.nereid_user: abort(404) # Search for a post with same uri post_form = BlogPostForm(request.form, obj=self) with Transaction().set_context(blog_id=self.id): if request.method == 'POST' and post_form.validate(): self.title = post_form.title.data self.content = post_form.content.data self.allow_guest_comments = post_form.allow_guest_comments.data self.save() flash('Your post has been updated.') if request.is_xhr: return jsonify(success=True, item=self.serialize()) return redirect( url_for('blog.post.render', user_id=self.nereid_user.id, uri=self.uri)) if request.is_xhr: return jsonify( success=request.method != 'POST', # False for POST, else True errors=post_form.errors or None, ) return render_template('blog_post_edit.jinja', form=post_form, post=self)
def render(self, confirmation=None): """Render given sale order :param sale: ID of the sale Order :param confirmation: If any value is provided for this field then this page is considered the confirmation page. This also passes a `True` if such an argument is proved or a `False` """ NereidUser = Pool().get('nereid.user') # This Ugly type hack is for a bug in previous versions where some # parts of the code passed confirmation as a text confirmation = False if confirmation is None else True # Try to find if the user can be shown the order access_code = request.values.get('access_code', None) if current_user.is_anonymous(): if not access_code: # No access code provided, user is not authorized to # access order page return NereidUser.unauthorized_handler() if access_code != self.guest_access_code: # Invalid access code abort(403) else: if self.party.id != request.nereid_user.party.id: # Order does not belong to the user abort(403) return render_template( 'sale.jinja', sale=self, confirmation=confirmation )
def download_file(self, attachment_id): """ Returns the file for download. The wonership of the task or the project is checked automatically. """ attachment_obj = Pool().get('ir.attachment') work = None if request.args.get('project', None): work = self.get_project(request.args.get('project', type=int)) if request.args.get('task', None): work = self.get_task(request.args.get('task', type=int)) if not work: # Neither task, nor the project is specified raise abort(404) attachment_ids = attachment_obj.search([ ('id', '=', attachment_id), ('resource', '=', '%s,%d' % (self._name, work.id)) ]) if not attachment_ids: raise abort(404) attachment = attachment_obj.browse(attachment_ids[0]) with tempfile.NamedTemporaryFile(delete=False) as f: f.write(attachment.data) return send_file( f.name, attachment_filename=attachment.name, as_attachment=True )
def update_comment(self, task_id, comment_id): """ Update a specific comment. """ project_obj = Pool().get('project.work') nereid_user_obj = Pool().get('nereid.user') # allow modification only if the user is an admin or the author of # this ticket task = project_obj.browse(task_id) comment = self.browse(comment_id) assert task.type == "task" assert comment.project.id == task.id # Allow only admins and author of this comment to edit it if nereid_user_obj.is_project_admin(request.nereid_user) or \ comment.updated_by == request.nereid_user: self.write(comment_id, {'comment': request.form['comment']}) else: abort(403) if request.is_xhr: comment_record = self.browse(comment_id) html = render_template('comment.jinja', comment=comment_record) return jsonify({ 'success': True, 'html': html, 'state': project_obj.browse(task.id).state, }) return redirect(request.referrer)
def render(cls, user_id, uri): "Render the blog post" NereidUser = Pool().get('nereid.user') if 're_captcha_public' in CONFIG.options and request.is_guest_user: comment_form = GuestCommentForm( captcha={'ip_address': request.remote_addr} ) else: comment_form = PostCommentForm() user = NereidUser(user_id) posts = cls.search([ ('nereid_user', '=', user.id), ('uri', '=', uri), ]) if not posts: abort(404) # if only one post is found then it is rendered and # if more than one are found then the first one is rendered post = posts[0] if not (post.state == 'Published' or request.nereid_user == post.nereid_user): abort(403) if request.is_xhr: return jsonify(post.serialize()) return render_template( 'blog_post.jinja', post=post, comment_form=comment_form, poster=user )
def stream_via_token(cls, token): ''' Set token user to online and publish presence of this user to all friends. ''' NereidUser = Pool().get('nereid.user') if hasattr(current_app, 'redis_client'): redis_client = current_app.redis_client else: redis_client = Redis( CONFIG.get('redis_host', 'localhost'), int(CONFIG.get('redis_port', 6379)) ) key = 'chat:token:%s' % token if not redis_client.exists(key): abort(404) nereid_user = NereidUser(int(redis_client.get(key))) nereid_user.broadcast_presence() return Response( cls.generate_event_stream( nereid_user.id, Transaction().cursor.dbname ), mimetype='text/event-stream' )
def render(self, post_id): "Render the blog post" post = self.browse(post_id) if not post: abort(404) return render_template('blog_post.jinja', post=post)
def process(cls, sale, payment_method_id): """Begins the payment processing. Returns a response object if a redirect to third party website is required, else processes the payment. :param sale: Browse Record of the Sale :param payment_method_id: ID of payment method """ Sale = Pool().get('sale.sale') try_to_authorize = ( request.nereid_website.payment_mode == 'auth_if_available' ) payment_method = cls(payment_method_id) allowed_gateways = cls._get_available_gateways( sale.invoice_address.country ) if payment_method not in allowed_gateways: current_app.logger.error("Payment method %s is not valid" % payment_method.name) abort(403) payment_method_obj = Pool().get(payment_method.model.model) Sale.write([sale], {'payment_method': payment_method.id}) if try_to_authorize and hasattr(payment_method_obj, 'authorize'): return payment_method_obj.authorize(sale) else: return payment_method_obj.capture(sale)
def get_available_methods(cls): """Return the JSONified list of shipment gateways available This is a XHR only method If type is specified as address then an address lookup is done The get could be made with the following options: 1. address Checks if user is logged in Checks if its a valid address of the user extracts to_address from it 2. Individually specify the following: street, streetbis, city, postal_code, subdivision, country The subdivision and country are not expanded into the ISO codes or names because doing that may not be required by many methods and some methods may requrie codes while others require name. So it is better to pass the ID of the same and the get_rate method of each decide if they want to expand into CODE or NAME """ Address = Pool().get('party.address') if 'address' in request.args: if request.is_guest_user: abort(403) # If not validated as user's address this could lead to # exploitation by ID address_id = request.args.get('address', type=int) if address_id not in [ a.id for a in request.nereid_user.party.addresses ]: abort(403) address = Address(address_id) result = cls._get_available_methods( street=address.street, streetbis=address.streetbis, city=address.city, zip=address.zip, subdivision=address.subdivision.id, country=address.country.id, ) else: # Each specified manually result = cls._get_available_methods( street=request.args.get('street'), streetbis=request.args.get('streetbis'), city=request.args.get('city'), zip=request.args.get('zip'), subdivision=int(request.args.get('subdivision')), country=int(request.args.get('country')), ) return jsonify( result=[(g['id'], g['name'], g['amount']) for g in result] )
def validate_for_product_inventory(self): """ This method validates the sale line against the product's inventory attributes. This method requires request context. """ if has_request_context() and not self.product.can_buy_from_eshop(): flash(_("This product is no longer available")) abort(redirect(request.referrer))
def validate_for_product_inventory(self): """ This method validates the sale line against the product's inventory attributes. This method requires request context. """ if has_request_context() and not self.product.can_buy_from_eshop(): flash(_('This product is no longer available')) abort(redirect(request.referrer))
def render(cls, uri): """ Renders the template """ try: article, = cls.search([('uri', '=', uri)]) except ValueError: abort(404) return render_template(article.template, article=article)
def _add_or_update(self, product_id, quantity, action='set'): """ Raise 400 if someone tries to add gift card to cart using add_to_cart method """ Product = Pool().get('product.product') if Product(product_id).is_gift_card: abort(400) return super(Sale, self)._add_or_update(product_id, quantity, action)
def get_post_for_uri(cls, uri): """ Return post for current user and uri """ posts = cls.search([ ('uri', '=', uri), ('nereid_user', '=', request.nereid_user.id), ]) if not posts: abort(404) return posts[0]
def send_message(cls): ''' POST: Publish messages to a thread. thread_id: thread id of session. message: message to send to a thread. type: (optional) Type of message, Default: plain :return: JSON ad { 'UUID': 'unique id of message', } ''' try: chat, = cls.search([ ('thread', '=', request.form['thread_id']), ('members.user', '=', request.nereid_user.id) ]) except ValueError: abort(404) data_message = { "timestamp": datetime.utcnow().isoformat(), "type": "message", "message": { "subject": None, "text": request.form['message'], "type": request.form.get('type', 'plain'), "language": "en_US", "attachments": [], "id": unicode(uuid.uuid4()), "thread": chat.thread, "sender": request.nereid_user.serialize(), 'members': map( lambda m: m.user.serialize(), chat.members ) } } # Save the message to messages list cls.save_message(chat, request.nereid_user, data_message) # Publish my presence too request.nereid_user.broadcast_presence() # Publish the message to the queue system for receiver in chat.members: receiver.user.publish_message(data_message) return jsonify({ 'UUID': unicode(data_message['message']['id']), })
def _handle_guest_checkout_with_regd_email(cls, email): """ Handle a situation where a guest user tries to checkout but there is already a registered user with the email. Depending on your company policy you might want top do several things like allowing the user to checkout and also send him an email that you could have used the account for checkout etc. By default, the behavior is NOT to allow such checkouts and instead flash a message and quit """ flash(_('A registration already exists with this email. ' 'Please login or contact customer care')) abort(redirect(url_for('nereid.checkout.default.checkout')))
def menu_for(cls, identifier, ident_field_value, objectified=False): """ Returns a dictionary of menu tree :param identifier: The unique identifier from which the menu has to be chosen :param ident_field_value: The value of the field that has to be looked up on model with search on ident_field :param objectified: The value returned is the active record of the menu identified rather than a tree. """ # First pick up the menu through identifier try: menu, = cls.search([ ('unique_identifier', '=', identifier), ('website', '=', request.nereid_website.id), ]) except ValueError: current_app.logger.error("Menu %s could not be identified" % identifier) abort(404) # Get the data from the model MenuItem = Pool().get(menu.model.model) try: root_menu_item, = MenuItem.search( [(menu.identifier_field.name, '=', ident_field_value)], limit=1) except ValueError: current_app.logger.error("Menu %s could not be identified" % ident_field_value) abort(500) if objectified: return root_menu_item cache_key = key_from_list([ Transaction().cursor.dbname, Transaction().user, Transaction().language, identifier, ident_field_value, 'nereid.cms.menu.menu_for', ]) rv = cache.get(cache_key) if rv is None: rv = menu._generate_menu_tree(root_menu_item) cache.set(cache_key, rv, 60 * 60) return rv
def menu_for(cls, identifier, ident_field_value, objectified=False): """ Returns a dictionary of menu tree :param identifier: The unique identifier from which the menu has to be chosen :param ident_field_value: The value of the field that has to be looked up on model with search on ident_field :param objectified: The value returned is the active record of the menu identified rather than a tree. """ # First pick up the menu through identifier try: menu, = cls.search([ ('unique_identifier', '=', identifier), ('website', '=', request.nereid_website.id), ]) except ValueError: current_app.logger.error( "Menu %s could not be identified" % identifier) abort(404) # Get the data from the model MenuItem = Pool().get(menu.model.model) try: root_menu_item, = MenuItem.search( [(menu.identifier_field.name, '=', ident_field_value)], limit=1) except ValueError: current_app.logger.error( "Menu %s could not be identified" % ident_field_value) abort(500) if objectified: return root_menu_item cache_key = key_from_list([ Transaction().cursor.dbname, Transaction().user, Transaction().language, identifier, ident_field_value, 'nereid.cms.menu.menu_for', ]) rv = cache.get(cache_key) if rv is None: rv = menu._generate_menu_tree(root_menu_item) cache.set(cache_key, rv, 60 * 60) return rv
def parse_command(command): """ Parse the given commands to a dictionary of command parameters :param command: A special command to be parsed :return: A tuple of the operation to be done and parameters for it """ command = unquote(str(command)) try: operation, params = command.split(',', 1) except ValueError: abort(404) return operation, dict([arg.split('_') for arg in params.split(',')])
def render_wishlist(self): """ Render specific wishlist of current user. rename wishlist on post and delete on delete request """ Wishlist = Pool().get('wishlist.wishlist') if self.nereid_user != current_user and \ (request.method != "GET" or not self.is_public): abort(404) if request.method == "POST" and request.form.get('name'): name = request.form.get('name') wishlist = Wishlist.search([ ('nereid_user', '=', current_user.id), ('id', '!=', self.id), ('name', '=', name), ], limit=1) if wishlist: flash( _( 'Wishlist with name: %(name)s already exists.', name=name ) ) return redirect(request.referrer) else: self.name = name self.is_public = True if request.form.get('is_public') \ else False self.save() flash(_('Wishlist Updated')) if request.is_xhr: return 'success', 200 return redirect(request.referrer) elif request.method == "DELETE": Wishlist.delete([self]) if request.is_xhr: # TODO: send serialized data of current wishlist return 'success', 200 return url_for('wishlist.wishlist.render_wishlists') return render_template('wishlist.jinja', wishlist=self)
def add_shipping_line(cls, sale, shipment_method_id): ''' Extract the shipping method and rate from the form Then create a new line or overwrite and existing line in the sale order with the name of the method and price and is_shipping_line flag set ''' SaleLine = Pool().get('sale.line') address = sale.shipment_address available_methods = cls._get_available_methods( street=address.street, streetbis=address.streetbis, city=address.city, zip=address.zip, subdivision=address.subdivision.id, country=address.country.id, ) for method in available_methods: if method['id'] == shipment_method_id: if not method['amount']: current_app.logger.debug( "Shipping amount is %s" % method['amount']) break values = { 'description': 'Shipping (%s)' % method['name'], 'sale': sale.id, 'unit_price': Decimal(str(method['amount'])), 'quantity': 1, 'is_shipping_line': True, } existing_shipping_lines = SaleLine.search([ ('sale', '=', sale.id), ('is_shipping_line', '=', True) ]) if existing_shipping_lines: SaleLine.write(existing_shipping_lines, values) else: SaleLine.create([values]) break else: current_app.logger.debug( 'Selected shipment method (%s) not in ' + 'shipping_quote (%s) in session' % (shipment_method_id, session['shipping_quote']) ) abort(403) return True
def availability(cls, uri): """ Returns the following information for a product: +-------------------+-----------------------------------------------+ | quantity | Available readily to buy | +-------------------+-----------------------------------------------+ | forecast_quantity | Forecasted quantity, if the site needs it | +-------------------+-----------------------------------------------+ .. note:: To modify the availability, or to send any additional information, it is recommended to subclass the :py:meth:`~get_availability` and implement your custom logic. For example, you might want to check stock with your vendor for back orders or send a message like `Only 5 pieces left` :param uri: URI of the product for which the availability needs to be found :return: JSON object """ try: product, = cls.search([ ('displayed_on_eshop', '=', True), ('uri', '=', uri), ]) except ValueError: return abort(404) return jsonify(product.get_availability())
def add_comment(cls, user_id, uri): ''' Add a comment ''' warnings.warn( "add_comment will be deprecated in 3.2 use render_comment instead.", DeprecationWarning, ) # Comments can only be added to published posts posts = cls.search([ ('nereid_user', '=', user_id), ('uri', '=', uri), ], limit=1) if not posts: abort(404) return posts[0].render_comments()
def get_task(cls, task_id): """ Common base for fetching the task while validating if the user can use it. :param task_id: Task Id of project to fetch. """ tasks = cls.search([("id", "=", task_id), ("type", "=", "task")]) if not tasks: raise abort(404) if not tasks[0].parent.can_write(request.nereid_user, silent=True): # If the user is not allowed to access this project then dont let raise abort(403) return tasks[0]
def render_wishlist(self): """ Render specific wishlist of current user. rename wishlist on post and delete on delete request """ Wishlist = Pool().get('wishlist.wishlist') if self.nereid_user != current_user and \ (request.method != "GET" or not self.is_public): abort(404) if request.method == "POST" and request.form.get('name'): name = request.form.get('name') wishlist = Wishlist.search([ ('nereid_user', '=', current_user.id), ('id', '!=', self.id), ('name', '=', name), ], limit=1) if wishlist: flash( _('Wishlist with name: %(name)s already exists.', name=name)) return redirect(request.referrer) else: self.name = name self.is_public = True if request.form.get('is_public') \ else False self.save() flash(_('Wishlist Updated')) if request.is_xhr: return 'success', 200 return redirect(request.referrer) elif request.method == "DELETE": Wishlist.delete([self]) if request.is_xhr: # TODO: send serialized data of current wishlist return 'success', 200 return url_for('wishlist.wishlist.render_wishlists') return render_template('wishlist.jinja', wishlist=self)
def send_message(cls): ''' POST: Publish messages to a thread. thread_id: thread id of session. message: message to send to a thread. type: (optional) Type of message, Default: plain :return: JSON ad { 'UUID': 'unique id of message', } ''' try: chat, = cls.search([('thread', '=', request.form['thread_id']), ('members.user', '=', request.nereid_user.id)]) except ValueError: abort(404) data_message = { "timestamp": datetime.utcnow().isoformat(), "type": "message", "message": { "subject": None, "text": request.form['message'], "type": request.form.get('type', 'plain'), "language": "en_US", "attachments": [], "id": unicode(uuid.uuid4()), "thread": chat.thread, "sender": request.nereid_user.serialize(), 'members': map(lambda m: m.user.serialize(), chat.members) } } # Save the message to messages list cls.save_message(chat, request.nereid_user, data_message) # Publish my presence too request.nereid_user.broadcast_presence() # Publish the message to the queue system for receiver in chat.members: receiver.user.publish_message(data_message) return jsonify({ 'UUID': unicode(data_message['message']['id']), })
def check_authorization(self, authorization=None): """ Ensures that the authorization in the current request is valid. Aborts if its invalid. if authorization is None, check for the authorization header sent by apple passbook. """ if authorization is None: # validate the authentication token # The Authorization header is supplied; its value is the word # "ApplePass", followed by a space, followed by the # authorization token as specified in the pass. _, authorization = request.headers['Authorization'].split(' ') if authorization != self.authentication_token: abort(401)
def parse_command(command): """ Parse the given commands to a dictionary of command parameters :param command: A special command to be parsed :return: A tuple of the operation to be done and parameters for it """ command = unquote(unicode(command)) try: operation, params = command.split(',', 1) except ValueError: abort(404) return operation, dict( map(lambda arg: arg.split('_'), params.split(',')) )
def render(cls, uri, page=1): """ Renders the category """ Article = Pool().get('nereid.cms.article') # Find in cache or load from DB try: category, = cls.search([('unique_name', '=', uri)]) except ValueError: abort(404) articles = Pagination( Article, [('category', '=', category.id)], page, cls.per_page ) return render_template( category.template, category=category, articles=articles)
def download_invoice(self): """ Allow user to download invoice. """ Report = Pool().get('account.invoice', type='report') if self.party != current_user.party: abort(403) vals = Report.execute([self.id], {}) with tempfile.NamedTemporaryFile(delete=False) as file: file.write(vals[1]) return send_file( file.name, as_attachment=True, attachment_filename=vals[3], )
def change_guest_permission(self): "Change guest permission of the post" if self.nereid_user != request.nereid_user: abort(404) allow_guest_comment = request.form.get('allow_guest_comments') self.allow_guest_comments = True if allow_guest_comment == 'true' \ else False self.save() if request.is_xhr: return jsonify({ 'success': True, }) return redirect( url_for('blog.post.render', user_id=self.nereid_user.id, uri=self.uri))
def manage_spam(self): "Mark the comment as spam" if not self.post.nereid_user == request.nereid_user: abort(403) self.is_spam = request.form.get('spam', False, type=bool) self.save() if request.is_xhr: return jsonify({ 'success': True, }) else: flash('The comment has been updated') return redirect( url_for('blog.post.render', user_id=self.post.nereid_user.id, uri=self.post.uri))
def atom_feed(cls, uri): """ Returns atom feed for articles published under a particular category. """ try: category, = cls.search([ ('unique_name', '=', uri), ], limit=1) except ValueError: abort(404) feed = AtomFeed("Articles by Category %s" % category.unique_name, feed_url=request.url, url=request.host_url) for article in category.published_articles: feed.add(**article.serialize(purpose='atom')) return feed.get_response()
def wishlist_product(cls): """ Add/Remove product in wishlist. If wishlist_id is passed then search for wishlist and add/remove product else create a default wishlist and add product. :params wishlist: Get the id of wishlist product: Get product id action: add or remove, add will add product to wishlist. remove will unlink product from wishlist """ Product = Pool().get('product.product') wishlist_id = request.form.get("wishlist", type=int) if wishlist_id: try: wishlist, = cls.search([ ('id', '=', wishlist_id), ('nereid_user', '=', current_user.id), ]) except ValueError: raise ValidationError("Wishlist not valid!") else: wishlist = cls._search_or_create_wishlist() product = Product.search([ ('id', '=', request.form.get("product", type=int)), ('displayed_on_eshop', '=', True), ('template.active', '=', True), ], limit=1) if not product or request.form.get('action') not in ['add', 'remove']: abort(404) cls.write([wishlist], { 'products': [(request.form.get('action'), product)], }) if request.is_xhr: # TODO: Send serailized data of wishllist return 'success', 200 return redirect( url_for('wishlist.wishlist.render_wishlist', active_id=wishlist.id))
def change_state(self): "Change the state of the post" if self.nereid_user != request.nereid_user: abort(404) state = request.form.get('state') assert (state in ('publish', 'archive', 'draft')) getattr(self, str(state))([self]) if request.is_xhr: return jsonify({ 'success': True, 'new_state': self.state, }) flash('Your post is now %s' % self.state) return redirect( url_for('blog.post.render', user_id=self.nereid_user.id, uri=self.uri))
def _transform_static_file(self, commands, extension, filename): """ Transform the static file and send the transformed file :param commands: A list of commands separated by / :param extension: The image format to use :param filename: The file to which the transformed image needs to be written """ image_file = Image.open(BytesIO(self.file_binary)) parse_command = TransformationCommand.parse_command for command in commands.split('/'): operation, params = parse_command(command) if operation not in self.allowed_operations: abort(404) image_file = getattr(self, operation)(image_file, **params) image_file.save(filename)
def get_task(cls, task_id): """ Common base for fetching the task while validating if the user can use it. :param task_id: Task Id of project to fetch. """ tasks = cls.search([ ('id', '=', task_id), ('type', '=', 'task'), ]) if not tasks: raise abort(404) if not tasks[0].parent.can_write(request.nereid_user, silent=True): # If the user is not allowed to access this project then dont let raise abort(403) return tasks[0]
def atom_feed(cls, id): """ Returns the atom feed for all articles published under a certain author """ Article = Pool().get('nereid.cms.article') try: articles = Article.search([ ('author', '=', id), ('state', '=', 'published'), ]) except: abort(404) feed = AtomFeed("Articles by Author %s" % cls(id).display_name, feed_url=request.url, url=request.host_url) for article in articles: feed.add(**article.serialize(purpose='atom')) return feed.get_response()