Пример #1
0
    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()
            ]
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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
            )
        })
Пример #5
0
    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
Пример #6
0
    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)
Пример #7
0
    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)
        })
Пример #8
0
    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'))
Пример #9
0
    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
        )
Пример #10
0
    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
        )
Пример #11
0
    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'))
Пример #12
0
    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)
Пример #13
0
    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)
Пример #14
0
    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)
Пример #15
0
    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
        ))
Пример #16
0
    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()
            ]
Пример #17
0
    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)
Пример #18
0
    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
        )
Пример #19
0
    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
        )
Пример #20
0
    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)
Пример #21
0
    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
        )
Пример #22
0
    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'
        )
Пример #23
0
    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)
Пример #24
0
    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)
Пример #25
0
    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]
        )
Пример #26
0
 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))
Пример #27
0
 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))
Пример #28
0
 def render(cls, uri):
     """
     Renders the template
     """
     try:
         article, = cls.search([('uri', '=', uri)])
     except ValueError:
         abort(404)
     return render_template(article.template, article=article)
Пример #29
0
 def render(cls, uri):
     """
     Renders the template
     """
     try:
         article, = cls.search([('uri', '=', uri)])
     except ValueError:
         abort(404)
     return render_template(article.template, article=article)
Пример #30
0
    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)
Пример #31
0
    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)
Пример #32
0
    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]
Пример #33
0
    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]
Пример #34
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']),
        })
Пример #35
0
    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')))
Пример #36
0
    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
Пример #37
0
    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
Пример #38
0
    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(',')])
Пример #39
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)
Пример #40
0
    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
Пример #41
0
    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())
Пример #42
0
    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())
Пример #43
0
    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()
Пример #44
0
    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]
Пример #45
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)
Пример #46
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']),
        })
Пример #47
0
    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(','))
        )
Пример #49
0
    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)
Пример #50
0
    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],
        )
Пример #51
0
    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))
Пример #52
0
    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()
Пример #53
0
    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))
Пример #54
0
    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()
Пример #55
0
    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))
Пример #56
0
    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))
Пример #57
0
    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)
Пример #58
0
    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]
Пример #59
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()