Ejemplo n.º 1
0
class CategoryController(RestController):
    allow_only = predicates.has_any_permission('manage',
                                               'lawyer', msg=l_('Only for admin or lawyer'))

    @expose('json')
    @validate({
        'id': CategoryExistValidator(required=True),
    }, error_handler=validation_errors_response)
    def get_one(self, id, **kw):
        qa = Category.query.get(_id=ObjectId(id))
        return dict(qa=qa)

    @expose('json')
    def get_all(self):
        query = {'_owner': {'$in': [request.identity['user']._id, None]}, 'visible': True}
        categories = Category.query.find(query).sort('_id').all()
        return dict(categories=categories)

    @decode_params('json')
    @expose('json')
    @validate({
        'workspace_name': StringLengthValidator(min=2),
    }, error_handler=validation_errors_response)
    def create(self, workspace_name=None, **kw):
        user = request.identity['user']
        ws = Category.query.find({'name': str(workspace_name), '_owner': user._id}).first()
        if ws:
            response.status_code = 412
            return dict(errors={'workspace_name': 'This category already exists'})

        workspace = Category(
            visible=True,
            name=str(workspace_name),
            _owner=user._id
        )

        flash(_("Workspace %s successfully created!" % workspace.name))
        return dict(workspaces=self.get_all())

    @decode_params('json')
    @expose('json')
    @validate({
        'workspace_id': CategoryExistValidator(required=True),
    }, error_handler=validation_errors_response)
    def delete(self, workspace_id=None, **kw):
        workspace = Category.query.get(_id=ObjectId(workspace_id))
        if not workspace.owner:
            flash(_('This workspace can not be deleted'), 'warning')
            return dict(workspaces=self.get_all())
        Qa.query.remove({'_category': ObjectId(workspace_id)})
        Output.query.remove({'_category': ObjectId(workspace_id)})
        Precondition.query.remove({'_category': ObjectId(workspace_id)})
        documents = Document.query.find({'_category': ObjectId(workspace_id)}).all()
        doc = [document._id for document in documents]
        Questionary.query.remove({'_document': {'$in': doc}})
        Document.query.remove({'_id': {'$in': doc}})
        Category.query.remove({'_id': ObjectId(workspace_id)})
        flash(_("Category and all entities associated deleted"))
        return dict(workspaces=self.get_all())
Ejemplo n.º 2
0
 def test_category_exist_validator_with_not_existing_category(self):
     with test_context(self.app):
         validator = CategoryExistValidator()
         try:
             res = validator._validate_python('5757ce79c42d752bde919318')
         except ValidationError:
             assert True
         else:
             assert False
Ejemplo n.º 3
0
 def test_category_exist_validator_with_obj_not_valid(self):
     with test_context(self.app):
         validator = CategoryExistValidator()
         try:
             res = validator._validate_python('not_obj_id')
         except ValidationError:
             assert True
         else:
             assert False
Ejemplo n.º 4
0
 def test_category_exist_validator(self):
     category1 = self._get_category('Area 1')
     validator = CategoryExistValidator()
     try:
         res = validator._validate_python(str(category1._id))
     except ValidationError:
         assert False
     else:
         assert True
Ejemplo n.º 5
0
class QuestionaryController(BaseController):
    def _before(self, *args, **kw):
        tmpl_context.sidebar_section = "questionaries"

    allow_only = predicates.has_any_permission(
        'manage', 'lawyer', msg=l_('Only for admin or lawyer'))

    @expose('ksweb.templates.questionary.index')
    @paginate('entities',
              items_per_page=int(tg.config.get('pagination.items_per_page')))
    @validate({'workspace': CategoryExistValidator(required=True)})
    def index(self, workspace, **kw):
        user = request.identity['user']
        documents_id = [
            ObjectId(documents._id)
            for documents in model.Document.document_available_for_user(
                user_id=user._id, workspace=workspace).all()
        ]
        entities = model.Questionary.query.find({
            '$or': [{
                '_user': ObjectId(user._id)
            }, {
                '_owner': ObjectId(user._id)
            }],
            '_document': {
                '$in': documents_id
            }
        }).sort('title')
        return dict(
            page='questionary-index',
            fields={
                'columns_name': [
                    _('Title'),
                    _('Owner'),
                    _('Shared with'),
                    _('Created on'),
                    _('Completion %')
                ],
                'fields_name':
                ['title', '_owner', '_user', 'creation_date', 'completion']
            },
            entities=entities,
            actions=False,
            actions_content=[_('Export')],
            workspace=workspace)

    @decode_params('json')
    @expose('json')
    @validate(
        {
            'questionary_title': StringLengthValidator(min=2),
            'document_id': DocumentExistValidator(required=True),
            'email_to_share': EmailValidator(),
        },
        error_handler=validation_errors_response)
    def create(self,
               questionary_title=None,
               document_id=None,
               email_to_share=None,
               **kw):
        #  create questionary for himself
        owner = request.identity['user']
        if email_to_share:
            user = model.User.by_email_address(email_to_share)

            if not user:
                user = model.User(
                    user_name=email_to_share,
                    email_address=email_to_share,
                    display_name=email_to_share,
                )
        else:
            user = owner

        questionary = model.Questionary(
            title=questionary_title,
            _user=user._id,
            _owner=owner._id,
            _document=ObjectId(document_id),
        )

        if email_to_share:
            from tgext.mailer import get_mailer
            from tgext.mailer import Message
            mailer = get_mailer(request)
            share_url = tg.url('/dashboard',
                               params={'share_id': user._id},
                               qualified=True)
            message = Message(
                subject=_("Invite to a KSWEB document"),
                sender="*****@*****.**",
                recipients=[user.email_address],
                body=_(
                    "Hi, you were invited to compile the following document %s "
                    "at the following url %s" %
                    (questionary_title, share_url)))
            mailer.send_immediately(message)
            flash(
                _("Questionary succesfully created and shared to %s" %
                  email_to_share))
        return dict(questionary=questionary)

    @expose('ksweb.templates.questionary.compile')
    @expose('json')
    @validate(
        {
            '_id': QuestionaryExistValidator(required=True),
            'workspace': CategoryExistValidator(required=True),
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this questionary.'),
            field='_id',
            entity_model=model.Questionary))
    def compile(self, _id, workspace, **kwargs):
        questionary = model.Questionary.query.get(_id=ObjectId(_id))
        return dict(questionary=questionary,
                    quest_compiled=questionary.evaluate_questionary,
                    html=self.get_questionary_html(_id),
                    workspace=workspace)

    @expose('odt:ksweb.templates.questionary.questionary',
            content_type='application/vnd.oasis.opendocument.text')
    @validate({
        '_id': QuestionaryExistValidator(required=True),
    },
              error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this questionary.'),
            field='_id',
            entity_model=model.Questionary))
    def download(self, _id):
        questionary = model.Questionary.query.get(_id=ObjectId(_id))
        response.headerlist.append(
            ('Content-Disposition',
             'attachment;filename=%s.odt' % questionary._id))
        return dict(content=self.get_questionary_html(_id).striptags())

    @staticmethod
    def get_questionary_html(quest_id):
        questionary = model.Questionary.query.get(_id=ObjectId(quest_id))
        questionary_compiled = Template(questionary.document.html)

        output_values, qa_values = dict(), dict()

        for output_dict in questionary.document.content:
            _id = ObjectId(output_dict['content'])
            if output_dict['content'] in questionary.output_values and \
                    questionary.output_values[output_dict['content']]['evaluation']:
                output = model.Output.query.get(_id=_id)
                output_values['output_' + str(_id)] = output.render(
                    questionary.output_values)
            else:
                # this clear useless output placeholder
                output_values['output_' + str(_id)] = ''
        questionary_compiled = questionary_compiled.safe_substitute(
            **output_values)
        questionary_compiled = Template(questionary_compiled)

        for qa_id, resp in questionary.qa_values.items():
            qa_values['qa_' + qa_id] = Markup.escape(resp['qa_response'])

        return Markup(questionary_compiled.safe_substitute(**qa_values))

    @expose('json')
    @decode_params('json')
    @validate(
        {
            '_id': QuestionaryExistValidator(required=True),
            'qa_id': QAExistValidator(required=True),
            'qa_response': StringLengthValidator(min=1, strip=False),
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this questionary.'),
            field='_id',
            entity_model=model.Questionary))
    def responde(self, _id=None, qa_id=None, qa_response=None, **kwargs):
        questionary = model.Questionary.query.get(_id=ObjectId(_id))
        #  Check if the qa response is valid
        qa = model.Qa.query.get(_id=ObjectId(qa_id))
        if qa.type == "single" and not qa_response in qa.answers:
            response.status_code = 412
            return dict(errors={'qa_response': _('Invalid answer')})

        if qa.type == "multi":
            #  check each qa_response if is in qa.answers
            if isinstance(qa_response, basestring):
                qa_response = [qa_response]

                # This comment is needed for to allow users to 'not response' a question
                # For disable this, just uncomment followings rows

                # for elem in qa_response:
                #     if not elem in qa.answers:
                #         response.status_code = 412
                #         return dict(errors={'qa_response': _('Invalid answer')})

        if not questionary.qa_values:
            order_number = 0
        else:
            order_number = max([
                questionary.qa_values[elem]['order_number']
                for elem in questionary.qa_values
            ]) + 1
        questionary.qa_values[qa_id] = {
            'qa_response': qa_response,
            'order_number': order_number
        }

        # Not sure about flush here
        DBSession.flush(questionary)
        quest_compiled = questionary.evaluate_questionary

        return dict(questionary=questionary,
                    quest_compiled=quest_compiled,
                    html=self.get_questionary_html(_id))

    @expose('ksweb.templates.questionary.completed')
    @validate(
        {
            '_id': QuestionaryExistValidator(required=True),
            'workspace': CategoryExistValidator(required=True),
        },
        error_handler=validation_errors_response)
    def completed(self, _id=None, workspace=None):
        questionary = model.Questionary.query.get(_id=ObjectId(_id))
        completed = questionary.evaluate_questionary
        if not completed:
            return redirect('/questionary/compile',
                            params=dict(quest_complited=completed,
                                        workspace=workspace))

        questionary_compiled = Template(questionary.document.html)
        output_values, qa_values = dict(), dict()

        for output_dict in questionary.document.content:
            _id = ObjectId(output_dict['content'])
            if questionary.output_values.get(output_dict['content']):
                output = model.Output.query.get(_id=_id)
                output_values['output_' + str(_id)] = output.render(
                    questionary.output_values)
            else:
                # this clear useless output placeholder
                output_values['output_' + str(_id)] = ''

        questionary_compiled = questionary_compiled.safe_substitute(
            **output_values)
        questionary_compiled = Template(questionary_compiled)

        for qa_id, resp in questionary.qa_values.items():
            qa_values['qa_' + qa_id] = Markup.escape(resp['qa_response'])

        questionary_compiled = questionary_compiled.safe_substitute(
            **qa_values)

        return dict(questionary_compiled=Markup(questionary_compiled),
                    workspace=workspace)

    @expose('json')
    @decode_params('json')
    @validate({'_id': QuestionaryExistValidator(required=True)},
              error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this questionary.'),
            field='_id',
            entity_model=model.Questionary))
    def previous_question(self, _id=None, **kwargs):
        questionary = model.Questionary.query.get(_id=ObjectId(_id))
        previous_response = {}

        if questionary.qa_values:
            last_order_number = max([
                questionary.qa_values[qa_val]['order_number']
                for qa_val in questionary.qa_values
            ])
            last_question_answered = [
                qa_val for qa_val in questionary.qa_values
                if questionary.qa_values[qa_val]['order_number'] ==
                last_order_number
            ][0]
            previous_response = questionary.qa_values[last_question_answered][
                'qa_response']
            questionary.qa_values.pop(last_question_answered, None)
            DBSession.flush_all()

        return dict(questionary=questionary,
                    quest_compiled=questionary.evaluate_questionary,
                    html=self.get_questionary_html(_id),
                    previous_response=previous_response)
Ejemplo n.º 6
0
Archivo: qa.py Proyecto: fossabot/ksweb
class QaController(RestController):
    def _before(self, *args, **kw):
        tmpl_context.sidebar_section = "qas"

    allow_only = predicates.has_any_permission(
        'manage', 'lawyer', msg=l_('Only for admin or lawyer'))

    @expose('ksweb.templates.qa.index')
    @paginate('entities',
              items_per_page=int(tg.config.get('pagination.items_per_page')))
    @validate({
        'workspace': CategoryExistValidator(required=True),
    },
              error_handler=validation_errors_response)
    def get_all(self, workspace=None, **kw):
        return dict(page='qa-index',
                    fields={
                        'columns_name':
                        [_('Label'), _('Question'),
                         _('Filter')],
                        'fields_name':
                        ['title', 'question', 'parent_precondition']
                    },
                    entities=model.Qa.qa_available_for_user(
                        request.identity['user']._id, workspace),
                    actions=False,
                    workspace=workspace)

    @expose('json')
    @validate({
        'id': QAExistValidator(required=True),
    },
              error_handler=validation_errors_response)
    def get_one(self, id, **kw):
        qa = model.Qa.query.find({
            '_id': ObjectId(id),
            '_owner': request.identity['user']._id
        }).first()
        return dict(qa=qa)

    @expose('json')
    @validate({'workspace': CategoryExistValidator(required=True)})
    def get_single_or_multi_question(self, workspace):
        questions = model.Qa.query.find({
            'type': {
                '$in': ['single', 'multi']
            },
            '_owner': request.identity['user']._id,
            '_category': ObjectId(workspace)
        }).all()
        return dict(questions=[{
            '_id': qa._id,
            'title': qa.title
        } for qa in questions])

    @expose('json')
    @expose('ksweb.templates.qa.new')
    @validate({
        'workspace': CategoryExistValidator(required=True),
    })
    def new(self, workspace, **kw):
        return dict(errors=None,
                    workspace=workspace,
                    referrer=kw.get('referrer'),
                    qa={
                        'question': kw.get('question_content', None),
                        'title': kw.get('question_title', None),
                        '_parent_precondition': kw.get('precondition_id', None)
                    })

    @decode_params('json')
    @expose('json')
    @validate(
        {
            'title': StringLengthValidator(min=2),
            'category': CategoryExistValidator(required=True),
            'question': StringLengthValidator(min=2),
            'tooltip': StringLengthValidator(min=0, max=100),
            'link': StringLengthValidator(min=0, max=100),
            'answer_type': OneOfValidator(values=model.Qa.QA_TYPE,
                                          required=True),
            'precondition': PreconditionExistValidator(required=False),
        },
        error_handler=validation_errors_response)
    def post(self,
             title,
             category,
             question,
             tooltip,
             link,
             answer_type,
             precondition=None,
             answers=None,
             **kw):
        if not self._are_answers_valid(answer_type, answers):
            response.status_code = 412
            return dict(
                errors={'answers': _('Please add at least one more answer')})

        user = request.identity['user']

        qa = model.Qa(_owner=user._id,
                      _category=ObjectId(category),
                      _parent_precondition=ObjectId(precondition)
                      if precondition else None,
                      title=title,
                      question=question,
                      tooltip=tooltip,
                      link=link,
                      type=answer_type,
                      answers=answers,
                      public=True,
                      visible=True)

        self._autofill_qa_filters(qa)
        return dict(errors=None, _id=ObjectId(qa._id))

    @decode_params('json')
    @expose('json')
    @validate(
        {
            '_id': QAExistValidator(required=True),
            'title': StringLengthValidator(min=2),
            'category': CategoryExistValidator(required=True),
            'question': StringLengthValidator(min=2),
            'tooltip': StringLengthValidator(min=0, max=100),
            'link': StringLengthValidator(min=0, max=100),
            'answer_type': OneOfValidator(values=model.Qa.QA_TYPE,
                                          required=True),
            'precondition': PreconditionExistValidator(required=False),
        },
        error_handler=validation_errors_response)
    def put(self,
            _id,
            title,
            category,
            question,
            tooltip,
            link,
            answer_type,
            precondition=None,
            answers=None,
            **kw):
        if not self._are_answers_valid(answer_type, answers):
            response.status_code = 412
            return dict(
                errors={'answers': _('Please add at least one more answer')})

        check = self.get_related_entities(_id)

        if check.get("entities"):
            entity = dict(_id=_id,
                          _category=category,
                          title=title,
                          entity='qa',
                          question=question,
                          tooltip=tooltip,
                          link=link,
                          type=answer_type,
                          _parent_precondition=precondition,
                          answers=answers)

            session.data_serializer = 'pickle'
            session[
                'entity'] = entity  # overwrite always same key for avoiding conflicts
            session.save()

            return dict(redirect_url=tg.url('/resolve',
                                            params=dict(workspace=category)))

        qa = model.Qa.query.get(_id=ObjectId(_id))
        qa._category = ObjectId(category)
        qa._parent_precondition = to_object_id(precondition)
        qa.title = title
        qa.question = question
        qa.tooltip = tooltip
        qa.question = question
        qa.link = link
        qa.type = answer_type
        qa.answers = answers
        self._autofill_qa_filters(qa)

        return dict(errors=None)

    @expose('ksweb.templates.qa.new')
    @validate({'_id': QAExistValidator(model=True)},
              error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(msg=l_(u'You can not edit this Q/A'),
                             field='_id',
                             entity_model=model.Qa))
    def edit(self, _id, workspace=None, **kw):
        ws = model.Category.query.find({'_id': ObjectId(workspace)}).first()
        if not ws:
            return tg.abort(404)
        qa = model.Qa.query.find({'_id': ObjectId(_id)}).first()
        return dict(qa=qa, workspace=ws._id, errors=None)

    @expose('json')
    @decode_params('json')
    @validate({
        '_id': QAExistValidator(required=True),
    },
              error_handler=validation_errors_response)
    def human_readable_details(self, _id, **kw):
        qa = model.Qa.query.find({'_id': ObjectId(_id)}).first()
        return dict(qa=qa)

    @decode_params('json')
    @expose('json')
    def get_related_entities(self, _id):
        """
        This method return ALL entities (Precondition simple) that have inside the given _id
        :param _id:
        :return:
        """

        preconditions_related = model.Precondition.query.find({
            'type':
            'simple',
            'condition':
            ObjectId(_id)
        })
        entities = list(preconditions_related)
        return {'entities': entities, 'len': len(entities)}

    def _autofill_qa_filters(self, qa):
        user = request.identity['user']
        if qa.type == 'text':  # model.Qa.QA_TYPE[0]
            model.Precondition(_owner=user._id,
                               _category=ObjectId(qa._category),
                               title=qa.title + _(' -> ANSWERED'),
                               type='simple',
                               condition=[qa._id, ''])
        else:
            base_precond = []
            for answer in qa.answers:
                prec = model.Precondition(
                    _owner=user._id,
                    _category=ObjectId(qa._category),
                    title=qa.title + ' -> %s' % answer,
                    type='simple',
                    condition=[qa._id, answer],
                )
                base_precond.append(prec)

            condition = []
            for prc in base_precond[:-1]:
                condition.append(prc._id)
                condition.append('or')

            condition.append(base_precond[-1]._id)

            created_precondition = model.Precondition(
                _owner=user._id,
                _category=ObjectId(qa._category),
                title=qa.title + _(' -> ANSWERED'),
                type='advanced',
                condition=condition)

    def _are_answers_valid(self, answer_type, answers):
        if (answer_type == "single" and len(answers) < 2) or\
           (answer_type == "multi" and len(answers) < 1):
            return False
        return True
Ejemplo n.º 7
0
class PreconditionSimpleController(RestController):
    def _before(self, *args, **kw):
        tmpl_context.sidebar_section = "preconditions"

    @expose('ksweb.templates.precondition.simple.new')
    @validate({'workspace': CategoryExistValidator(required=True)})
    def new(self, workspace, **kw):
        return dict(page='precondition-new',
                    workspace=workspace,
                    qa_value=kw.get('qa_value'),
                    precondition={
                        'question_content': kw.get('question_content', None),
                        'question_title': kw.get('question_title', None)
                    })

    @decode_params('json')
    @expose('json')
    @validate(
        {
            'title':
            StringLengthValidator(min=2),
            'category':
            CategoryExistValidator(required=True),
            'question':
            QAExistValidator(required=True),
            'answer_type':
            OneOfValidator(values=[u'have_response', u'what_response'],
                           required=True),
        },
        error_handler=validation_errors_response)
    def post(self, title, category, question, answer_type, interested_response,
             **kw):
        user = request.identity['user']

        qa = model.Qa.query.get(_id=ObjectId(question))

        #  CASO BASE in cui risco a creare un filtro semplice per definizione e' quella di che venga solamente selezionata una risposta
        if len(interested_response) == 1:
            #  La risposta e' solo una creo un filtro semplice
            created_precondition = model.Precondition(
                _owner=user._id,
                _category=ObjectId(category),
                title=title,
                type='simple',
                condition=[ObjectId(question), interested_response[0]])
        else:
            #  CASO AVANZATO sono state selezionate piu' risposte, devo prima creare tutte i filtri semplici e poi creare quella complessa
            if answer_type == "have_response":
                #  Create one precondition simple for all possibility answer to question
                #  After that create a complex precondition with previous simple precondition
                interested_response = qa.answers

            if answer_type == "what_response":
                #  Create one precondition simple for all selected answer to question
                #  After that create a complex precondition with previous simple precondition

                if len(interested_response) <= 1:
                    response.status_code = 412
                    return dict(
                        errors={
                            'interested_response':
                            _('Please select at least one answer')
                        })

            base_precond = []
            for resp in interested_response:
                prec = model.Precondition(_owner=user._id,
                                          _category=ObjectId(category),
                                          title="%s_%s" %
                                          (qa.title.upper(), resp.upper()),
                                          type='simple',
                                          condition=[ObjectId(question), resp],
                                          public=True,
                                          visible=False)
                base_precond.append(prec)

            condition = []
            for prc in base_precond[:-1]:
                condition.append(prc._id)
                condition.append('or')

            condition.append(base_precond[-1]._id)

            created_precondition = model.Precondition(
                _owner=user._id,
                _category=ObjectId(category),
                title=title,
                type='advanced',
                condition=condition)

        #flash(_("Now you can create an output <a href='%s'>HERE</a>" % lurl('/output?workspace='+ str(category))))

        return dict(precondition_id=str(created_precondition._id), errors=None)

    @decode_params('json')
    @expose('json')
    @validate(
        {
            '_id':
            PreconditionExistValidator(required=True),
            'title':
            StringLengthValidator(min=2),
            'category':
            CategoryExistValidator(required=True),
            'question':
            QAExistValidator(required=True),
            'answer_type':
            OneOfValidator(values=[u'what_response'], required=True),
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this filter.'),
            field='_id',
            entity_model=model.Precondition))
    def put(self, _id, title, category, question, answer_type,
            interested_response, **kw):

        check = self.get_related_entities(_id)
        if check.get("entities"):
            entity = dict(_id=_id,
                          title=title,
                          condition=[question, interested_response],
                          _category=category,
                          entity='precondition/simple')
            session[
                'entity'] = entity  # overwrite always same key for avoiding conflicts
            session.save()
            return dict(redirect_url=tg.url('/resolve',
                                            params=dict(workspace=category)))

        precondition = model.Precondition.query.get(_id=ObjectId(_id))
        precondition.title = title
        precondition.condition = [ObjectId(question), interested_response]
        precondition._category = category

        return dict(errors=None, redirect_url=None)

    @decode_params('json')
    @expose('json')
    def get_related_entities(self, _id):
        return get_related_entities_for_filters(_id)

    @expose('ksweb.templates.precondition.simple.new')
    @validate(
        {
            '_id': PreconditionExistValidator(),
            'workspace': CategoryExistValidator()
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this filter.'),
            field='_id',
            entity_model=model.Precondition))
    def edit(self, _id, workspace, **kw):
        precondition = model.Precondition.query.find({
            '_id':
            ObjectId(_id),
            '_category':
            ObjectId(workspace)
        }).first()
        return dict(precondition=precondition,
                    workspace=workspace,
                    errors=None)

    @expose('json')
    @decode_params('json')
    @validate({
        '_id': PreconditionExistValidator(required=True),
    },
              error_handler=validation_errors_response)
    def human_readable_details(self, _id, **kw):
        precondition = model.Precondition.query.find({
            '_id': ObjectId(_id)
        }).first()
        return dict(precondition=precondition)
Ejemplo n.º 8
0
class PreconditionAdvancedController(RestController):
    def _before(self, *args, **kw):
        tmpl_context.sidebar_section = "preconditions"
        tmpl_context.sidebar_precondition_advanced = "preconditions-advanced"

    @expose('ksweb.templates.precondition.advanced.new')
    @validate({'workspace': CategoryExistValidator(required=True)})
    def new(self, workspace, **kw):
        return dict(precondition={}, workspace=workspace)

    @decode_params('json')
    @expose('json')
    @validate(
        {
            'title': StringLengthValidator(min=2),
            'category': CategoryExistValidator(required=True),
            'conditions': LengthValidator(min=1, required=True),
        },
        error_handler=validation_errors_response)
    def post(self, title, category, conditions, **kw):
        error, condition = self._marshall_complex_filter(conditions)
        if error:
            response.status_code = 412
            return dict(errors=error)

        user = request.identity['user']
        model.Precondition(_owner=user._id,
                           _category=ObjectId(category),
                           title=title,
                           type='advanced',
                           condition=condition)

        flash(
            _("Now you can create an output <a href='%s'>HERE</a>" %
              lurl('/output?workspace=' + str(category))))
        return dict(errors=None)

    @decode_params('json')
    @expose('json')
    @validate(
        {
            '_id': PreconditionExistValidator(required=True),
            'title': StringLengthValidator(min=2),
            'category': CategoryExistValidator(required=True),
            'conditions': LengthValidator(min=1, required=True),
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this filter.'),
            field='_id',
            entity_model=model.Precondition))
    def put(self, _id, title, category, conditions, **kw):
        error, condition = self._marshall_complex_filter(conditions)
        if error:
            response.status_code = 412
            return dict(errors=error)

        check = self.get_related_entities(_id)

        if check.get("entities"):
            entity = dict(
                _id=_id,
                title=title,
                condition=list(map(str, condition)),
                _category=category,
                entity='precondition/advanced',
            )
            session[
                'entity'] = entity  # overwrite always same key for avoiding conflicts
            session.save()
            return dict(redirect_url=tg.url('/resolve'))

        precondition = model.Precondition.query.get(_id=ObjectId(_id))
        precondition.title = title
        precondition.condition = condition
        precondition._category = category

        return dict(errors=None, redirect_url=None)

    @expose('ksweb.templates.precondition.advanced.new')
    @validate(
        {
            '_id': PreconditionExistValidator(),
            'workspace': CategoryExistValidator(),
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this filter.'),
            field='_id',
            entity_model=model.Precondition))
    def edit(self, _id, workspace=None, **kw):
        precondition = model.Precondition.query.find({
            '_id': ObjectId(_id)
        }).first()
        return dict(precondition=precondition,
                    workspace=workspace,
                    errors=None)

    @decode_params('json')
    @expose('json')
    def get_related_entities(self, _id):
        return get_related_entities_for_filters(_id)

    def _marshall_complex_filter(self, filters):
        boolean_str = ""
        marshalled_filter = []

        for _f in filters:
            if _f['type'] == 'precondition':
                p = model.Precondition.query.get(_id=ObjectId(_f['content']))
                error = None if p else {'conditions': _('Filter not found.')}
                boolean_str += "True "
                marshalled_filter.append(ObjectId(_f['content']))
            elif _f['type'] == 'operator':
                o = _f['content'] in model.Precondition.PRECONDITION_OPERATOR
                error = None if o else {'conditions': _('Filter not found.')}
                boolean_str += _f['content'] + " "
                marshalled_filter.append(_f['content'])
            else:
                error = {'conditions': _('Invalid operator')}

        try:
            eval(boolean_str)
        except SyntaxError as e:
            error = {'conditions': _('Syntax error')}

        return error, marshalled_filter
Ejemplo n.º 9
0
class OutputController(RestController):
    def _validate_precondition_with_qa(self, precondition, content):
        if not precondition:
            return dict(errors={'content': _('Filter not found')})
        #  Check content precondition element
        precond = model.Precondition.query.find({
            '_id': ObjectId(precondition)
        }).first()
        related_qa = precond.response_interested
        #  Check elem['content'] contain the obj id of the related
        for elem in content:
            if elem['type'] == 'qa_response':
                if elem['content'] not in related_qa.keys():
                    response.status_code = 412
                    return dict(
                        errors={
                            'content':
                            _('The question %s is not related to the filter') %
                            elem['title']
                        })
        return dict()

    def _before(self, *args, **kw):
        tmpl_context.sidebar_section = "outputs"
        tmpl_context.id_obj = kw.get('_id')

    allow_only = predicates.has_any_permission(
        'manage', 'lawyer', msg=l_('Only for admin or lawyer'))

    @expose('ksweb.templates.output.index')
    @paginate('entities',
              items_per_page=int(tg.config.get('pagination.items_per_page')))
    @validate({'workspace': CategoryExistValidator(required=True)})
    def get_all(self, workspace, **kw):
        return dict(page='output-index',
                    fields={
                        'columns_name':
                        [_('Label'), _('Filter'),
                         _('Content')],
                        'fields_name': ['title', 'precondition', 'content']
                    },
                    entities=model.Output.output_available_for_user(
                        request.identity['user']._id, workspace),
                    actions=False,
                    workspace=workspace)

    @expose('json')
    @expose('ksweb.templates.output.new')
    @validate({'workspace': CategoryExistValidator(required=True)})
    def new(self, workspace, **kw):
        tmpl_context.sidebar_output = "output-new"
        return dict(output={'_precondition': kw.get('precondition_id', None)},
                    workspace=workspace,
                    errors=None)

    @decode_params('json')
    @expose('json')
    @validate(
        {
            'title': StringLengthValidator(min=2),
            'content': OutputContentValidator(),
            'ks_editor': StringLengthValidator(min=2),
            'category': CategoryExistValidator(required=True),
            'precondition': PreconditionExistValidator(),
        },
        error_handler=validation_errors_response)
    def post(self, title, content, category, precondition, **kw):
        content = content or []

        #  Check content precondition element
        error = self._validate_precondition_with_qa(precondition, content)
        if error:
            return error

        user = request.identity['user']
        model.Output(_owner=user._id,
                     _category=ObjectId(category),
                     _precondition=ObjectId(precondition),
                     title=title,
                     content=content,
                     public=True,
                     visible=True,
                     html=kw['ks_editor'])
        return dict(errors=None)

    @expose('json')
    @decode_params('json')
    @validate(
        {
            '_id': OutputExistValidator(required=True),
            'title': StringLengthValidator(min=2),
            'content': OutputContentValidator(),
            'category': CategoryExistValidator(required=True),
            'precondition': PreconditionExistValidator(),
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this output.'),
            field='_id',
            entity_model=model.Output))
    def put(self, _id, title, content, category, precondition, **kw):
        content = content or []

        #  Check content precondition element
        error = self._validate_precondition_with_qa(precondition, content)
        if error:
            return error

        check = self.get_related_entities(_id)

        if check.get("entities"):
            entity = dict(_id=_id,
                          title=title,
                          content=content,
                          _category=category,
                          _precondition=precondition,
                          entity='output',
                          html=kw['ks_editor'])
            session[
                'entity'] = entity  # overwrite always same key for avoiding conflicts
            session.save()
            return dict(redirect_url=tg.url('/resolve',
                                            params=dict(workspace=category)))

        output = model.Output.query.find({'_id': ObjectId(_id)}).first()
        output.title = title
        output._category = ObjectId(category)
        output._precondition = ObjectId(precondition)
        output.content = content
        output.html = kw['ks_editor']

        return dict(errors=None, redirect_url=None)

    @expose('ksweb.templates.output.new')
    @validate(
        {
            '_id': OutputExistValidator(required=True),
            'workspace': CategoryExistValidator(required=True),
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this output.'),
            field='_id',
            entity_model=model.Output))
    def edit(self, _id, workspace, **kw):
        output = model.Output.query.find({
            '_id': ObjectId(_id),
            '_category': ObjectId(workspace)
        }).first()
        tmpl_context.sidebar_output = "output-edit"
        return dict(output=output, workspace=workspace, errors=None)

    @expose('json')
    def sidebar_output(self, _id=None, workspace=None):  #pragma: no cover
        res = list(
            model.Output.query.aggregate([{
                '$match': {
                    '_owner': request.identity['user']._id,
                    '_id': {
                        '$ne': ObjectId(_id)
                    },
                    'visible': True,
                    '_category': ObjectId(workspace)
                }
            }, {
                '$group': {
                    '_id': '$_category',
                    'output': {
                        '$push': "$$ROOT",
                    }
                }
            }]))

        #  Insert category name into res
        for e in res:
            e['category_name'] = model.Category.query.get(
                _id=ObjectId(e['_id'])).name

        return dict(outputs=res)

    @expose('json')
    @decode_params('json')
    @validate({
        '_id': OutputExistValidator(required=True),
    },
              error_handler=validation_errors_response)
    def human_readable_details(self, _id, **kw):
        output = model.Output.query.get(_id=ObjectId(_id))

        return dict(
            output={
                '_id': output._id,
                'title': output.title,
                'content': output.human_readbale_content,
                'human_readbale_content': output.human_readbale_content,
                '_owner': output._owner,
                'owner': output.owner.display_name,
                '_precondition': output._precondition,
                'precondition': output.precondition.title,
                '_category': output._category,
                'category': output.category.name,
                'public': output.public,
                'visible': output.visible,
                'created_at': output.created_at
            })

    @decode_params('json')
    @expose('json')
    def get_related_entities(self, _id):
        """
        This method return ALL entities (Output, Document) that have inside a `content.content` the given _id
        :param _id:
        :return:
        """
        output_related = model.Output.query.find({
            "content.type": "output",
            "content.content": _id
        }).all()
        documents_related = model.Document.query.find({
            "content.type": "output",
            "content.content": _id
        }).all()
        entities = list(output_related + documents_related)
        return dict(entities=entities, len=len(entities))
Ejemplo n.º 10
0
class PreconditionController(BaseController):
    allow_only = predicates.has_any_permission('manage', 'lawyer',  msg=l_('Only for admin or lawyer'))
    
    def _before(self, *args, **kw):
        tmpl_context.sidebar_section = "preconditions"
        
    simple = PreconditionSimpleController()
    advanced = PreconditionAdvancedController()

    @expose('ksweb.templates.precondition.index')
    @paginate('entities', items_per_page=int(tg.config.get('pagination.items_per_page')))
    @validate({'workspace': CategoryExistValidator(required=True)})
    def index(self, workspace, **kw):
        return dict(
            page='precondition-index',
            fields={
                'columns_name': [l_('Label'), l_('Type'), l_('Owner')],
                'fields_name': ['title', 'type', 'owner']
            },
            entities=model.Precondition.precondition_available_for_user(request.identity['user']._id, workspace=workspace),
            actions_content=[l_('New Output'),l_('New Q/A')],
            workspace=workspace
        )

    @expose('json')
    def sidebar_precondition(self, workspace): #pragma: no cover
        res = list(model.Precondition.query.aggregate([
            {
                '$match': {
                    '_owner': request.identity['user']._id,
                    # 'visible': True
                    '_category': ObjectId(workspace)
                }
            },
            {
                '$group': {
                    '_id': '$_category',
                    'precondition': {'$push': "$$ROOT",}
                }
            }
        ]))

        #  Insert category name into res
        for e in res:
            e['category_name'] = model.Category.query.get(_id=ObjectId(e['_id'])).name

        return dict(precond=res)

    @expose('json')
    def available_preconditions(self, workspace=None):
        preconditions = Precondition.query.find({'_owner': request.identity['user']._id, 'visible': True, '_category': ObjectId(workspace)}).sort('title').all()
        return dict(preconditions=preconditions)

    @expose('json')
    @decode_params('json')
    @validate({
        'id': PreconditionExistValidator(required=True),
    }, error_handler=validation_errors_response)
    def qa_precondition(self, id, **kw):
        print(ObjectId(id))
        precondition = model.Precondition.query.get(_id=ObjectId(id))
        print(precondition.response_interested)
        return dict(qas=precondition.response_interested)
Ejemplo n.º 11
0
class ResolveController(BaseController):

    related_models = {
        'output': model.Output,
        'precondition/simple': model.Precondition,
        'precondition/advanced': model.Precondition,
        'qa': model.Qa,
        'document': model.Document
    }

    @decode_params('json')
    @expose('ksweb.templates.resolve.index')
    @with_entity_session
    @validate({
        'workspace': CategoryExistValidator(required=True),
    })
    def index(self, workspace, **kw):
        return dict(workspace=workspace, **kw)

    @expose()
    @with_entity_session
    @validate({'workspace': CategoryExistValidator(required=True)})
    def original_edit(self, workspace, **kw):
        entity = self._original_edit()
        flash(_(u'Entity %s successfully edited!') % entity.title)
        session.delete()
        return redirect(
            base_url=tg.url('/qa', params=dict(workspace=workspace)))

    @expose()
    @with_entity_session
    @validate({'workspace': CategoryExistValidator(required=True)})
    def clone_object(self, workspace, **kw):
        entity = self._clone_object()
        flash(_("%s successfully created!") % entity.title)
        session.delete()
        return redirect(
            base_url=tg.url('/qa', params=dict(workspace=workspace)))

    @expose('')
    @validate({'workspace': CategoryExistValidator(required=True)})
    def discard_changes(self, workspace, **kw):
        session.delete()
        flash(_(u'All the edits are discarded'))
        return redirect(
            base_url=tg.url('/qa', params=dict(workspace=workspace)))

    @expose('ksweb.templates.resolve.manually_resolve')
    @with_entity_session
    @validate({'workspace': CategoryExistValidator(required=True)})
    def manually_resolve(self, workspace, **kw):

        # fetch params from session
        entity = session.get('entity')

        return dict(entity=entity['entity'],
                    values=entity,
                    workspace=workspace)

    @decode_params('json')
    @expose('json')
    @with_entity_session
    def mark_resolved(self, list_to_new=None, list_to_old=None, **kw):

        entity = session.get('entity')

        if len(list_to_new) >= 1:
            if len(list_to_old) >= 1:
                # worst case, we have some objects that refer to new and other that refer ro old, need a clone
                self._clone_and_modify_(entity, list_to_new)
            else:
                # we can just edit old object because no one refer more to old object
                self._original_edit()
        else:
            # all objects refer to old, we can just edit old object
            self._original_edit()

        session.delete()
        flash(_(u'All the conflicts are successfully resolved'))
        return dict(errors=None)

    def _original_edit(self):

        # fetch params from session
        params = session.get('entity')

        # transform to ObjectId here because ObjectId is not JSON serializable
        params['_category'] = to_object_id(params.get('_category'))
        params['_precondition'] = to_object_id(params.get('_precondition'))

        # retrieve original object
        entity = self._get_entity(params['entity'], params['_id'])

        # popping non-related values
        params.pop('entity', None)

        # true edit
        for k, v in params.items():
            setattr(entity, k, v)

        # TODO: update..
        # self._find_and_modify(kw)
        return entity

    def _clone_object(self):
        params = session.get('entity')
        entity = self._get_entity(params['entity'], params['_id'])
        params['title'] += ' [NUOVO]'
        new_obj = clone_obj(self.related_models[params['entity']], entity,
                            params)
        return new_obj

    def _get_entity(self, entity_name, _id):
        model_ = self.related_models[entity_name]
        return model_.query.get(_id=ObjectId(_id))

    def _clone_and_modify_(self, obj_to_clone, to_edit):
        new_obj = self._clone_object()

        for obj in to_edit:
            entity = self._get_entity(obj['entity'], obj['_id'])
            if obj_to_clone['entity'] == 'output':
                # I have to search into:
                #     output.content
                #     document.content
                for elem in entity.content:
                    if elem['content'] == obj_to_clone['_id']:
                        elem['content'] = str(getattr(new_obj, '_id'))
                        elem['title'] = getattr(new_obj, 'title')

            elif obj_to_clone['entity'] in [
                    'precondition/simple', 'precondition/advanced'
            ]:
                # I have to search into:
                #     qa._parent_precondition
                #     output._precondition
                #     precondition.condition
                if entity.entity == 'qa' and entity._parent_precondition == ObjectId(
                        obj_to_clone['_id']):
                    entity._parent_precondition = new_obj._id
                elif entity.entity == 'output' and entity._precondition == ObjectId(
                        obj_to_clone['_id']):
                    entity._precondition = new_obj._id
                elif entity.entity == 'precondition/advanced':
                    for index, elem in enumerate(entity.condition):
                        if elem == ObjectId(obj_to_clone['_id']):
                            entity.condition[index] = new_obj._id

            elif obj_to_clone['entity'] == 'qa':
                # I have to search into:
                #     precondition.condition
                for index, elem in enumerate(entity.condition):
                    if elem == ObjectId(obj_to_clone['_id']):
                        entity.condition[index] = new_obj._id