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())
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
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
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
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)
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
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)
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
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))
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)
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