예제 #1
0
 def test_user_doesnt_have_all_permissions(self):
     environ = make_environ('gustavo',
                            permissions=['watch-tv', 'party', 'eat'])
     p = predicates.has_any_permission('jump', 'scream')
     self.eval_unmet_predicate(
         p, environ, 'The user must have at least one of the following '
         'permissions: jump, scream')
예제 #2
0
 def test_user_doesnt_have_all_permissions(self):
     environ = make_environ('gustavo', permissions=['watch-tv', 'party',
                                                    'eat'])
     p = predicates.has_any_permission('jump', 'scream')
     self.eval_unmet_predicate(p, environ,
         'The user must have at least one of the following '
         'permissions: jump, scream')
예제 #3
0
파일: category.py 프로젝트: fossabot/ksweb
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())
예제 #4
0
class VettingController(BaseController):
    """Sample controller-wide authorization"""
    
    #The predicate that must be met for all the actions in this controller:
    allow_only = has_any_permission('manage','accountsmanage','buyingmanage',
                                msg=l_('Only for people with the "manage" permission'))

    @expose()
    def index(self):
        redirect('vettingcont/menu')

    @expose('jistdocstore.templates.vettingindex')
    def menu(self):
        #flash(_("Secure Controller here"))
        return dict(page='Vetting Main Menu') 
예제 #5
0
class DocumentController(RestController):
    def _before(self, *args, **kw):
        tmpl_context.sidebar_section = "documents"

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

    @expose('ksweb.templates.document.index')
    @paginate('entities',
              items_per_page=int(tg.config.get('pagination.items_per_page')))
    @validate({'workspace': WorkspaceExistValidator(required=True)})
    def get_all(self, workspace, **kw):
        return dict(
            page='document-index',
            fields={
                'columns_name':
                [_('Title'),
                 _('Description'),
                 _('Version'),
                 _('License')],
                'fields_name': ['title', 'description', 'version', 'license']
            },
            entities=model.Document.document_available_for_user(
                request.identity['user']._id, workspace=workspace),
            actions_content=[_('Export'), _('Create Form')],
            workspace=workspace,
            download=True)

    @expose('ksweb.templates.document.new')
    @validate({'workspace': WorkspaceExistValidator(required=True)})
    def new(self, workspace, **kw):
        tmpl_context.sidebar_document = "document-new"
        return dict(document={}, workspace=workspace, errors=None)

    @decode_params('json')
    @expose('json')
    @validate(
        {
            'title': StringLengthValidator(min=2),
            'workspace': WorkspaceExistValidator(required=True),
            'html': DocumentContentValidator(strip=False),
            'description': StringLengthValidator(min=0),
            'license': StringLengthValidator(min=0, max=100),
            'version': StringLengthValidator(min=0, max=100),
            'tags': StringLengthValidator(min=0, max=100)
        },
        error_handler=validation_errors_response)
    def post(self, title, workspace, description, license, version, tags, html,
             **kw):
        user = request.identity['user']
        tags = {__.strip() for __ in tags.split(',')} if tags else []

        doc = model.Document(_owner=user._id,
                             _workspace=ObjectId(workspace),
                             title=title,
                             public=True,
                             visible=True,
                             html=html,
                             description=description,
                             license=license,
                             version=version,
                             tags=list(tags))
        return dict(errors=None)

    @decode_params('json')
    @expose('json')
    @validate(
        {
            '_id': DocumentExistValidator(required=True),
            'title': StringLengthValidator(min=2),
            'workspace': WorkspaceExistValidator(required=True),
            'html': DocumentContentValidator(strip=False),
            'description': StringLengthValidator(min=0),
            'license': StringLengthValidator(min=0, max=100),
            'version': StringLengthValidator(min=0, max=100),
            'tags': StringLengthValidator(min=0),
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this document.'),
            field='_id',
            entity_model=model.Document))
    def put(self, _id, title, html, workspace, description, license, version,
            tags, **kw):
        tags = {__.strip() for __ in tags.split(',')} if tags else []
        document = model.Document.query.find({'_id': ObjectId(_id)}).first()
        document.title = title
        document._workspace = ObjectId(workspace)
        document.html = html
        document.tags = list(tags)
        document.description = description
        document.license = license
        document.version = version
        return dict(errors=None)

    @expose('ksweb.templates.document.new')
    @validate(
        {
            '_id': DocumentExistValidator(required=True),
            'workspace': WorkspaceExistValidator(required=True)
        },
        error_handler=validation_errors_response)
    @require(
        CanManageEntityOwner(
            msg=l_(u'You are not allowed to edit this document.'),
            field='_id',
            entity_model=model.Document))
    def edit(self, _id, workspace, **kw):
        tmpl_context.sidebar_document = "document-new"
        document = model.Document.by_id(_id)
        return dict(document=document, workspace=workspace, errors=None)

    @expose('json')
    @decode_params('json')
    @validate({
        '_id': DocumentExistValidator(required=True),
    },
              error_handler=validation_errors_response)
    def human_readable_details(self, _id, **kw):
        # TODO: implement something meaningful
        document = model.Document.query.find({'_id': ObjectId(_id)}).first()
        return dict(document=document)

    @expose("json", content_type='application/json')
    @validate({
        '_id': DocumentExistValidator(required=True),
    },
              error_handler=validation_errors_response)
    def export(self, _id):
        document = model.Document.query.get(_id=ObjectId(_id))
        filename = slugify(document, document.title)
        response.headerlist.append(
            ('Content-Disposition',
             str('attachment;filename=%s.json' % filename)))
        encoded = json_render.encode(document.export())
        return json.dumps(json.loads(encoded), sort_keys=True, indent=4)

    @expose()
    @validate({
        'workspace': WorkspaceExistValidator(required=True),
    },
              error_handler=validation_errors_response)
    def import_document(self, workspace, file_import):
        owner = request.identity['user']._id
        file_content = file_import.file.read()
        importer = JsonImporter(file_content, ObjectId(workspace), owner)
        importer.run()
        tg.flash(_('Document successfully imported!'))
        return redirect(tg.url('/document', params=dict(workspace=workspace)))
예제 #6
0
class ReceptionController(BaseController):
    """Sample controller-wide authorization"""

    #The predicate that must be met for all the actions in this controller:
    allow_only = has_any_permission(
        'manage',
        'reception',
        msg=l_('Only for people with the "manage" permission'))

    @expose()
    def index(self):
        redirect('receptioncont/menu')

    @expose('jistdocstore.templates.receptionindex')
    def menu(self):
        #flash(_("Secure Controller here"))
        return dict(page='Reception: Main Menu')

    @expose('jistdocstore.templates.receptionconsole')
    def reception_console(self, **named):
        activeusers = DBS_ContractData.query(User).filter(
            User.active_status == 1).all()
        statcodeall = DBS_ContractData.query(JistContractStatusCodes).all()
        contracts = DBS_ContractData.query(JistContracts).filter(JistContracts.completed=="False"). \
               order_by(desc(JistContracts.jno)).all()
        pointlist = []
        productionlist = []
        accountslist = []
        for point in activeusers:
            if point:
                if point.user_id == 1:
                    pointlist.append({
                        'user_id': point.user_id,
                        'user_name': point.user_name,
                        'display_name': point.display_name
                    })
                    productionlist.append({
                        'user_id': point.user_id,
                        'user_name': point.user_name,
                        'display_name': point.display_name
                    })
                user = User.by_user_id(point.user_id)
                userpermissions = user.permissions
                for permis in userpermissions:
                    #print permis.permission_name
                    if permis.permission_name == 'productionmanage':
                        pointlist.append({
                            'user_id': point.user_id,
                            'user_name': point.user_name,
                            'display_name': point.display_name
                        })
                for permis in userpermissions:
                    #print permis.permission_name
                    if permis.permission_name == 'production':
                        productionlist.append({
                            'user_id':
                            point.user_id,
                            'user_name':
                            point.user_name,
                            'display_name':
                            point.display_name
                        })
        thishourrange = [hours for hours in range(06, 20)]
        thisminrange = [minutes for minutes in range(00, 60, 15)]
        thistimerange = [(thishour, thismin) for thishour in thishourrange
                         for thismin in thisminrange]
        #for x in range(0,61,15):
        #    print x
        return dict(page='Reception Console',
                    userlist=productionlist,
                    wip=contracts,
                    timeperiod=range(1, 9),
                    currentPage=1,
                    value=named,
                    value2=named)

    @expose('jistdocstore.templates.telephone_message_new')
    def telephone_messages(self, **named):
        """Handle the 'telephone messages' page."""
        #ajax_form = AjaxForm(id="myAjaxForm",
        #            fields=ReceptionTelephoneMessage(),
        #            target="output",
        #            action="do_save_new_message")
        #tmpl_context.form = ajax_form
        tmpl_context.form = add_new_reception_message

        return dict(page='Telephone messages search',
                    wip='',
                    currentPage=1,
                    value=named,
                    value2=named)

    @expose()
    def do_save_new_message(self, **kw):
        #listname = ['call_again','call_back','no_message']
        #for k,w in kw.iteritems():
        #    print k, w
        #return
        #del kw['sprox_id']
        newmessage = JistReceptionTelephoneMessages()
        #for k,w in kw.iteritems():
        #    print k,w
        #print kw['call_again']
        #print kw['call_back']
        #print kw['no_message']
        #newmessage.call_again = kw['call_again']
        #newmessage.call_back =kw['call_back']
        #newmessage.no_message =kw['no_message']
        username = request.identity['repoze.who.userid']
        usernow = User.by_user_name(username)
        newmessage.to_user = kw['toperson']
        newmessage.from_person = kw['telephonecall_person_calling']
        newmessage.message = kw['telephonecall_message']
        newmessage.return_tel = kw['telephonecall_returnno']
        newmessage.useridnew = usernow.user_id
        DBS_ContractData.add(newmessage)
        #DBS_ContractData.flush()
        #redirect('/receptioncont/telephone_messages')

    #@require(in_any_group("managers","logistics"))
    @expose('jistdocstore.templates.telephone_messages_all')
    def telephone_messages_all(self, **named):
        """Handle the 'telephone messages' page."""
        ajax_form = AjaxForm(id="myAjaxForm1",
                             fields=ReceptionTelephoneDateMessage(),
                             target="output",
                             action="do_search_telephone_messages")
        tmpl_context.form = ajax_form
        #tmpl_context.form = add_new_reception_message

        return dict(page='Telephone messages search',
                    wip='',
                    currentPage=1,
                    value=named,
                    value2=named)

    @expose()
    #@validate(ajax_form)
    def do_search_telephone_messages(self, **kw):
        if not kw['dateadded']:
            year = str(0)
        else:
            for k, w in kw.iteritems():
                requestdate = w.split('-')
                year = w.split('-')[0]
                month = w.split('-')[1]
                day = w.split('-')[2]
        if year == str(0):
            today = datetime.date(datetime.now())
            tup = today.timetuple()
        else:
            today = date(int(year), int(month), int(day))
            tup = today.timetuple()
        sttimestart = time(0, 0, 0)
        sttimeend = time(23, 59, 59)
        startdate = datetime.combine(today, sttimestart)
        enddate = datetime.combine(today, sttimeend)
        openorders = DBS_ContractData.query(JistReceptionTelephoneMessages).filter(JistReceptionTelephoneMessages.dateadded>=startdate). \
                                              filter(JistReceptionTelephoneMessages.dateadded<=enddate). \
                                              order_by(desc(JistReceptionTelephoneMessages.dateadded)).  \
                                              all()
        datenow = str(tup[0]) + '-' + str(tup[1]) + '-' + str(tup[2])
        supplier_text = "<H3 align='center'>Messages For %s</H3><p/>" % datenow
        table = "<table class='tablecontractdata'>"

        headerdata = """
                    <th>To User</th>
                    <th>From Person </th>
                    <th>Message</th>
                    <th>Return Tel Number</th>
                    <th>Added By</th>
                    <th>Date Time Added</th>
                    """
        sitedata = supplier_text + table + headerdata
        for k in openorders:
            tr = "<tr class='tablestandard'><td>"
            sitedatatemp = "<img src='/images/staffpics/%s.png' align=right/></td>" % str(
                k.to_user)
            fromperson = """ 
                            <td>%s</td>
                            """ % (k.from_person)
            messg = """ 
                            <td>%s</td>
                            """ % (k.message)
            returntel = """ 
                            <td width=20>%s</td>
                            """ % (k.return_tel)
            whoadded = "<td><img src='/images/staffpics/%s.png'/></td>" % str(
                k.useridnew)
            added = """ 
                            <td>%s</td>
                            """ % (k.dateadded)
            trclose = """
                        </tr>
                       """
            sitedata = sitedata+"</p>"+tr+sitedatatemp+ \
                    fromperson+ \
                    messg+returntel+whoadded+added+trclose
        sitedata = sitedata + "</table>"
        return sitedata

    #@require(in_any_group("managers","logistics"))
    @expose('jistdocstore.templates.outofoffice_movement_new')
    def out_of_office_movement_new(self, **named):
        """Handle the 'telephone messages' page."""
        #ajax_form = AjaxForm(id="myAjaxForm",
        #            fields=ReceptionTelephoneMessage(),
        #            target="output",
        #            action="do_save_new_message")
        #tmpl_context.form = ajax_form
        tmpl_context.form = add_new_out_of_office_notice

        return dict(page='Telephone Messages New',
                    wip='',
                    currentPage=1,
                    value=named,
                    value2=named)

    @expose()
    def do_save_new_out_of_office_movement(self, **kw):
        newnotice = JistOutOfOfficeNotices()
        username = request.identity['repoze.who.userid']
        usernow = User.by_user_name(username)
        #for k, w in kw.iteritems():
        #    print k,w
        #print
        #for col in newnotice.__table__._columns:
        #    print col
        #return

        if kw['toperson'] == 0:
            kw['toperson'] = 1
        elif kw['toperson'] == '':
            kw['toperson'] = 1
        newnotice.for_user = kw['toperson']
        if kw['outofoffice_otherdestination'] <> "":
            newnotice.other_destination = kw['outofoffice_otherdestination']
        else:
            newnotice.site = kw['sitename']
        newnotice.purpose = kw['outofoffice_purpose']
        newnotice.est_hours_there = kw['outofoffice_est_hours_there']
        newnotice.time_start = kw['outofoffice_timestart']
        newnotice.useridnew = usernow.user_id
        DBS_ContractData.add(newnotice)
        #DBS_ContractData.flush()
        #redirect('/receptioncont/out_of_office_movement_new')

    #@require(in_any_group("managers","logistics"))
    @expose('jistdocstore.templates.outofoffice_movement_all')
    def out_of_office_movement_all(self, **named):
        ajax_form = AjaxForm(id="myAjaxForm",
                             fields=OutOfOfficeDateMovments(),
                             target="output",
                             action="do_search_outofoffice_movements")
        tmpl_context.form = ajax_form
        #tmpl_context.form = add_new_reception_message

        return dict(page='Out of Office search',
                    wip='',
                    currentPage=1,
                    value=named,
                    value2=named)

    @expose()
    #@validate(ajax_form)
    def do_search_outofoffice_movements(self, **kw):
        if not kw['dateadded']:
            year = str(0)
        else:
            for k, w in kw.iteritems():
                requestdate = w.split('-')
                year = w.split('-')[0]
                month = w.split('-')[1]
                day = w.split('-')[2]
        if year == str(0):
            today = datetime.date(datetime.now())
            tup = today.timetuple()
        else:
            today = date(int(year), int(month), int(day))
            tup = today.timetuple()
        sttimestart = time(0, 0, 0)
        sttimeend = time(23, 59, 59)
        startdate = datetime.combine(today, sttimestart)
        enddate = datetime.combine(today, sttimeend)
        openorders = DBS_ContractData.query(JistOutOfOfficeNotices).filter(JistOutOfOfficeNotices.dateadded>=startdate). \
                                              filter(JistOutOfOfficeNotices.dateadded<=enddate). \
                                              order_by(desc(JistOutOfOfficeNotices.dateadded)).  \
                                              all()
        datenow = str(tup[0]) + '-' + str(tup[1]) + '-' + str(tup[2])
        supplier_text = "<H3 align='center'>Out Of Office Movements For %s</H3><p/>" % datenow
        table = "<table class='tablecontractdata'>"
        headerdata = """
                    <th>For User</th>
                    <th>Site </th>
                    <th>Other Destination</th>
                    <th>Purpose</th>
                    <th>Est Hr There</th>
                    <th>Time Start</th>
                    <th>Added By</th>
                    <th>Date Time Added</th>
                    """
        sitedata = supplier_text + table + headerdata
        for k in openorders:
            tr = "<tr class='tablestandard'><td>"
            sitedatatemp = "<img src='/images/staffpics/%s.png'/></td>" % str(
                k.for_user)
            if k.site:
                thissite = DBS_ContractData.query(JistContracts).filter(
                    JistContracts.jno == k.site).one()
                fromperson = """ 
                                <td>%s</td>
                                """ % (thissite.site)
                #print k.site
            else:
                fromperson = """ 
                                <td>%s</td>
                                """ % (k.site)

            callback = """ 
                            <td>%s</td>
                            """ % (k.other_destination)
            callagain = """ 
                            <td>%s</td>
                            """ % (k.purpose)
            nomsgs = """ 
                            <td>%s</td>
                            """ % (k.est_hours_there)
            messg = """ 
                            <td>%s</td>
                            """ % (k.time_start)
            returntel = "<td><img src='/images/staffpics/%s.png'/></td>" % str(
                k.useridnew)
            added = """ 
                            <td>%s</td>
                            """ % (k.dateadded)
            trclose = """
                        </tr>
                       """
            sitedata = sitedata+"</p>"+tr+sitedatatemp+ \
                    fromperson+callback+callagain+nomsgs+ \
                    messg+returntel+added+trclose
        sitedata = sitedata + "</table>"
        return sitedata
예제 #7
0
 def test_user_has_one_permission(self):
     environ = make_environ('gustavo', permissions=['watch-tv', 'party',
                                                    'eat'])
     p = predicates.has_any_permission('party', 'scream')
     self.eval_met_predicate(p, environ)
예제 #8
0
파일: root.py 프로젝트: puria/ksweb
 def index(self):
     if predicates.has_any_permission("manage", "lawyer"):
         redirect("/start")
     return dict()
예제 #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))
예제 #10
0
class BatchImportController(BaseController):
    """Docstring for batchimport."""

    allow_only = predicates.has_any_permission('Administrator', 'Membership')

    @expose('rocket.templates.generic')
    def index(self, *args, **kwargs):
        html = self.get_active_batchimport_html(*args, **kwargs)
        javascript = self.get_javascript_batchimport_onload()
        title = "Batch Import"
        kwargs = {
            'import_type_id' : 3,
            #'filename' : 'small_purchase.xlsx',
            #'filename' : 'small.xlsx',
        }
        #result = PurchaseImport(**kwargs).start_import()
        #result = MemberImport(**kwargs).start_import()
        #print(result)
        return dict(title=title, html=html, javascript=javascript)

    @expose()
    def get_batchimport_htmltbl(self, *args, **kwargs):
        usernow = request.identity.get('user', {})
        outputlist = []
        dbase_query = self.get_active_batchimport_list(**kwargs)
        for item in dbase_query:
            group_name = ''
            #rocket_group = GroupRocket.by_id(**{'id' : item.group_id})
            #if rocket_group:
            #    group_name = None
            #reject_html = f"<div class='batchimport_error action_link' batch_import_id='{item.id}'>{item.rejected_count}</div>" if item.rejected_count > 0 else item.rejected_count

            '''
            if item.total_count == (item.accepted_count + item.rejected_count):
                continue_html = "<img src='/images/icon_check.png' alt='Complete' title='Batch Import Complete'/>"
            else:
                #too_soon = item.added > add_minutes_to_date(datetime.now(), -MINS_TO_WAIT_FOR_IMPORT_CONTINUE)
                too_soon = True
                if not item.active: continue_html = "<img src='/images/icon_check.png' alt='Complete' title='Batch Import Complete'/>"
                elif item.active and not too_soon: continue_html = f"<div class='batchimport_continue action_link' batch_import_id='{item.id}'>Continue</div>"
                else: continue_html = f""" <div class="fa-1x"> <i class="text-dark fas fa-spinner fa-pulse"></i> </div> """
            '''
            continue_html = "<img src='/images/icon_check.png' alt='Complete' title='Batch Import Complete'/>"

            reject_html = item.rejected_count
            import_type = TYPEUTIL.get_name('batch_import_type', item.import_type_id)
            if not import_type: import_type = ""
            #continue_html = f"<div class='batchimport_continue action_link' batch_import_id='{item.id}'>Continue</div>"
            outputlist.append({
                'id' : f"<div class='batchimport_audit' batch_import_id='{item.id}'>{item.id}</div>",
                #'import_type_id' : get_name_from_id(ImportType, item.import_type_id),
                'import_type_id' : import_type.capitalize(),
                'group_id' : group_name,
                #'processed' : item.processed,
                'total_count' : item.total_count,
                'accepted_count' : item.accepted_count,
                #'pre_purchase_count' : item.pre_purchase_count,
                'rejected_count' : reject_html,
                'notes' : item.notes,
                'empty' : continue_html,
                             })
        dbcolumnlist=[
                'id',
                'import_type_id',
                'group_id',
                #'processed',
                'total_count',
                'accepted_count',
                #'pre_purchase_count',
                'rejected_count',
                'notes',
                'empty',
                    ]
        theadlist=[
                '',
                'Import Type',
                'Group',
                #'Processed',
                'Total',
                'Accepted',
                #'Pre-Purchase',
                'Rejected',
                'Notes',
                '',
                ]
        tdclasslist = [
                'action_link',
                '',
                '',
                #'',
                '',
                '',
                #'',
                '',
                '',
                'text-right',
                ]
        html = build_html_table(outputlist, dbcolumnlist, theadlist, "batchimport_table", tdclasslist)
        javascript = """
        <script>
            $(".batchimport_audit").click(function(){
                var kwargs = 'batch_import_id='+$(this).attr('batch_import_id');
                $('#dialogdiv').load('/batchimport/get_modal_audit_batchimport?', kwargs, function(data){
                    return false;
                });
            });
            $(".batchimport_error").click(function(){
                var kwargs = {batch_import_id: $(this).attr('batch_import_id')};
                $.redirect('/batchimport/errors', kwargs);
            });
            $(".batchimport_continue").click(function(){
                $(this).html('<div class="fa-1x"> <i class="text-dark fas fa-spinner fa-pulse"></i> </div>');
                var kwargs = 'batch_import_id='+$(this).attr('batch_import_id');
                $.post('/batchimport/restart_batch_import?', kwargs, function(data){
                    return false;
                });
            });
        </script>
        """
        return html + javascript

    @expose()
    def get_import_stats(self):
        returnable = ""
        if hasattr(self, 'running_import'):
            running_import = getattr(self, 'running_import')
            if running_import:
                if running_import.complete:
                    self.running_import = False
                    return returnable
            if running_import:
                if not running_import.complete: returnable = f"""
                <div>
                    <span>{self.running_import.import_type_name} Import Running</span>
                    <span class='ml-3'>Currently at Step: {self.running_import.import_status}</span>
                </div>
                <div>
                    <span class='ml-3'>Accepted: {self.running_import.accepted}</span>
                    <span class='ml-3'>Rejected: {self.running_import.rejected}</span>
                    <span class='ml-3'>Total: {self.running_import.total}</span>
                </div>
                    <script type='text/javascript'>
                        function refreshImportStats(){{
                            $('#import_stats').load('/batchimport/get_import_stats?', function(){{
                                return false
                            }});
                        }};
                        setTimeout(refreshImportStats, 1000);
                    </script>
                        """
        return returnable

    @expose()
    def get_active_batchimport_html(self, *args, **kwargs):
        print()
        kwargs['searchkey'] = SEARCHKEY
        usernow = request.identity.get('user', {})
        searchphrase = COMMON.get_searchphrase(**kwargs)
        batchimporttable = self.get_batchimport_htmltbl(**kwargs)
        import_stats = self.get_import_stats()
        html = f"""
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                <div class="card-header">
                    <div class="row d-flex">
                        <div class="col-md-6">
                            <h4 class="card-title">Batch Import</h4>
                        </div>
                        <div class="col-md-6 text-right">
                            <button id="refresh" class="btn btn-danger ml-auto">Refresh</button>
                            <button id="download_template" class="btn btn-primary ml-auto" data-toggle="modal">Download Template</button>
                            <button id="create_new_batchimport" class="btn btn-primary ml-auto" data-toggle="modal">Create New Batch Import</button>
                        </div>
                    </div>
                    <div class="row d-flex align-items-center">

                        <div class="col-md-6 d-flex">
                            <div class="col-md-8">
                                <input id='search' type="text" class="form-control search" name="searchphrase" placeholder="Search by Import Type or Group" value='{searchphrase}'>
                            </div>
                            <div class="col">
                                <button id='btn_search' class="btn btn-primary action_search">Search</button>
                                <button id='btn_reset' class="btn btn-primary">Reset</button>
                            </div>
                        </div>

                        <div class="col-md-6 d-flex text-right">
                            <div id="import_stats">
                                {import_stats}
                            </div>
                        </div>

                    </div>
                    <hr>
                </div>
                <div class="card-body">
                    <div id='div_batchimport_table' class="table-responsive">
                        {batchimporttable}
                    </div>
                </div>
                </div>
            </div>
            <div id='dialogdiv'></div>
        """
        return html

    @expose()
    def get_javascript_batchimport_onload(self, *args, **kwargs):
        javascript = """
        $("#refresh").click(function(){
            location.reload();
        });
        $("#download_template").click(function(){
            $('#dialogdiv').load('/batchimport/get_modal_download_template?', function(data){
                return false;
            });
        });
        $("#create_new_batchimport").click(function(){
            $('#dialogdiv').load('/batchimport/get_modal_new_batch_import?', function(data){
                return false;
            });
        });
        $('#btn_search').click(function(){
            var kwargs = 'searchphrase='+$('#search').val();
            $('#div_batchimport_table').load('/batchimport/get_batchimport_htmltbl', kwargs, function(data){
                return false;
            });
        });
        $('#btn_reset').click(function(){
            $('#search').val('').focus();
            $('#div_batchimport_table').load('/batchimport/get_batchimport_htmltbl', 'reset=true', function(data){
                return false;
            });
        });
        """
        return javascript

    @expose()
    def get_modal_download_template(self, *args, **kwargs):
        selectbox_importtypes = self.get_selectbox_import_type(**{'id': 'import_type_id', 'required': True})
        html = f"""
        <div class="modal fade" id="dialog_new_member_import" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
            <div class="modal-dialog modal-dialog-centered modal-lg">
                <div class="modal-content">
                    <div class="modal-header">
                        <h4 class="modal-title">Download Template</h4>
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
                            <i class="now-ui-icons ui-1_simple-remove"></i>
                        </button>
                    </div>
                    <div class="modal-body">
                        <form id='new_member_import'>
                            <div class="row">
                                <div class="col-md-12">
                                    <div class="form-group row">
                                        <label class="col-md-3 col-form-label" required>Template Type</label>
                                        <div class="col-md-9">
                                            {selectbox_importtypes}
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </form>
                    </div>
                    <div class="modal-footer">
                        <button id='btn_start_download' class="btn btn-primary">Download</button>
                        <button class="btn btn-outline-primary members_back" data-dismiss="modal">Cancel</button>
                    </div>
                </div>
            </div>
        </div>
        """
        javascript = """
        <script>
            $("#btn_start_download").click(function(){
                var selected = $('#import_type_id option:selected').val();
                var href_with_formserial = '/batchimport/download_template?import_type_id=' + selected;
                window.location = href_with_formserial
            });
            $('.members_back').click(function(){
                $('#dialog_new_member_import').modal('hide');
            });
            $('#dialog_new_member_import').modal();
        </script>
        """
        return html + javascript

    @expose()
    def get_modal_new_batch_import(self, *args, **kwargs):
        selectbox_importtypes = self.get_selectbox_import_type(**{'id': 'import_type_id', 'required': True})
        html = f"""
        <div class="modal fade" id="dialog_new_batch_import" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
            <div class="modal-dialog modal-dialog-centered modal-lg">
                <div class="modal-content">
                    <div class="modal-header">
                        <h4 class="modal-title">New Batch Import</h4>
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
                            <i class="now-ui-icons ui-1_simple-remove"></i>
                        </button>
                    </div>
                    <div class="modal-body">
                        <form id='new_batch_import'>
                            <div class="row">
                                <div class="col-md-12">
                                    <div class="form-group row">
                                        <label class="col-md-3 col-form-label" required>Import Type</label>
                                        <div class="col-md-9">
                                            {selectbox_importtypes}
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div id="div_product_selectbox" class="row">
                            </div>
                        </form>
                        <div class="row">
                            <div class="col-md-12">
                                <div class="form-group row">
                                    <div class='dropzone' id='dropzone_batch_import'></div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button id='btn_start_import' class="btn btn-primary">Import</button>
                        <button class="btn btn-outline-primary batches_back" data-dismiss="modal">Cancel</button>
                    </div>
                </div>
            </div>
        </div>
        """
        javascript = """
        <script>
            $(document).ready(function(){
                $('#import_type_id').change(function(){
                    var import_type_id = $('#import_type_id option:selected').val();
                    if(import_type_id){
                        var kwargs = 'import_type_id='+import_type_id;
                        $('#div_product_selectbox').load('/batchimport/get_batch_import_product_owner_selectbox_html?', kwargs, function(data){
                            return false;
                        });
                    }else{
                        $('#div_product_selectbox').empty();
                    };
                });

                setFormValidation('#new_batch_import');
                var batchDropzone = new Dropzone('#dropzone_batch_import', {
                    maxFiles: 1,
                    maxFilesize: 256,
                    parallelUploads: 1,
                    uploadMultiple: false,
                    autoProcessQueue: false,
                    acceptedFiles: '.xls, .xlsx, .ods',
                    url: '/batchimport/handle_file_upload',
                    params: {
                        // To pass extra keys into the uploader
                    },
                    success: function(file, response){
                        var result = JSON.parse(response);
                        if(result.success === true){
                            var product_owner_id = $('#product_owner_id option:selected').val();
                            var formserial = 'import_type_id='+$('#import_type_id option:selected').val();
                            formserial += '&filename='+result.name;
                            formserial += product_owner_id ? '&product_owner_id='+product_owner_id : '';
                            $.post('/batchimport/start_new_batch_import?'+formserial, function(data){
                                return false;
                            });
                            setTimeout(function(){
                                $('#dialog_new_batch_import').modal('hide');
                                $.redirect('/batchimport/index');
                            }, 1000);
                        };
                    },
                });
                $("#btn_start_import").click(function(){
                    var valid = FormIsValid('#new_batch_import');
                    if(valid){
                        batchDropzone.processQueue();
                    };
                });
                $('.batches_back').click(function(){
                    $('#dialog_new_batch_import').modal('hide');
                });
                $('#dialog_new_batch_import').modal();
            });
        </script>
        """
        return html + javascript

    @expose()
    def get_batch_import_product_owner_selectbox_html(self, *args, **kwargs):
        import_type_id = str_to_int(kwargs.get('import_type_id', None))
        purchase = TYPEUTIL.get_id_of_name('batch_import_type', 'purchase')
        if not import_type_id == purchase: return ''
        selectbox = PRODUCTCONT.get_selectbox_product_owner(**{'id' : 'product_owner_id'})
        return f"""
        <div class="col-md-12">
            <div class="form-group row">
                <label class="col-md-3 col-form-label" required>Product Owner</label>
                <div class="col-md-9">
                    {selectbox}
                </div>
            </div>
        </div>
        """

    @expose()
    def get_batch_import_audit_table(self, *args, **kwargs):
        dbase_query = self.get_active_batchimportaudit_list(*args, **kwargs)
        outputlist = []
        for item in dbase_query:
            outputlist.append({
                'audit_date_time' : item.audit_date_time,
                'audit' : item.audit,
                             })
        dbcolumnlist=[
                'audit_date_time',
                'audit',
                    ]
        theadlist=[
                'Date',
                'Audit',
                ]
        return build_html_table(outputlist, dbcolumnlist, theadlist, "batchimportaudit_table")

    @expose()
    def get_batch_import_info_html(self, *args, **kwargs):
        usernow = request.identity.get('user', {})
        batchimport = self.get_batchimport_by_id(**kwargs)
        img_active = "<span class='now-ui-icons ui-1_check text-green font-weight-bold'>"
        img_inactive = "<span class='now-ui-icons ui-1_simple-remove text-red font-weight-bold'>"
        #is_complete_load = img_active if batchimport.is_complete_load else img_inactive
        #is_complete_update = img_active if batchimport.is_complete_update else img_inactive
        is_complete_load = img_active
        is_complete_update = img_active
        import_type = TYPEUTIL.get_pretty_name('import_type', batchimport.import_type_id)
        #rocket = GroupRocket.by_id(**{'id' : batchimport.group_id})
        #group_name = group.get('name') if group else ''
        group_name = ""
        html = f"""
        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Type</label>
            <span class='font-italic'>{import_type}</span>
        </div>

        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Created</label>
            <span class='font-italic'>{batchimport.added}</span>
        </div>

        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Group</label>
            <span class='font-italic'>{group_name}</span>
        </div>

        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Accepted</label>
            <span class='font-italic'>{batchimport.accepted_count}</span>
        </div>

        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Total</label>
            <span class='font-italic'>{batchimport.total_count}</span>
        </div>

        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Rejected</label>
            <span class='font-italic'>{batchimport.rejected_count}</span>
        </div>

        <!--
        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Pre Purchased</label>
            <span class='font-italic'>pre purchase</span>
        </div>
        -->

        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Printed</label>
            <span class='font-italic'></span>
        </div>

        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Captured</label>
            <span class='font-italic'>{usernow.name}</span>
        </div>

        <div class="row col-md-6">
            <label class="col-md-6 col-form-label">Printed By</label>
            <span class='font-italic'>{usernow.name}</span>
        </div>

        <div class="row col-md-6 d-flex align-items-center">
            <label class="col-md-6 col-form-label">Load Complete?</label>
            {is_complete_load}
        </div>

        <div class="row col-md-6 d-flex align-items-center">
            <label class="col-md-6 col-form-label">Update Complete?</label>
            {is_complete_update}
        </div>

        <div class="row col-md-12">
            <label class="col-md-3 col-form-label">File Name</label>
            <span class='font-italic'>{batchimport.filename}</span>
        </div>

        """
        return html

    @expose()
    def get_modal_audit_batchimport(self, *args, **kwargs):
        batch_import_id = kwargs.get('batch_import_id', None)
        if not batch_import_id: return ''
        batch_import_info = self.get_batch_import_info_html(**kwargs)
        batch_import_audit_table = self.get_batch_import_audit_table(**kwargs)
        html = f"""
        <div class="modal fade" id="dialog_audit_batchimport" tabindex="-1" role="dialog" aria-labelledby="mybatchimportLabel" aria-hidden="true">
            <div class="modal-dialog modal-dialog-centered modal-lg">
                <div class="modal-content">
                    <div class="modal-header">
                        <div class="col-md-6">
                            <h4 class="card-title">Batch Import Audit Log</h4>
                        </div>
                    </div>
                    <div class="modal-body">
                        <div class="row col-md-12 d-flex f">
                            {batch_import_info}
                        </div>
                        <div id='div_audit_table row col-md-12'>
                            {batch_import_audit_table}
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button class="btn btn-outline-primary batchimport_back" data-dismiss="modal">Close</button>
                    </div>
                </div>
            </div>
        </div>
        """
        javascript = """
        <style>
            #div_audit_table {
                max-height: 300px;
                overflow-y: auto;
            };
        </style>
        <script>
        $('.batchimport_back').click(function(){
            $('#dialog_audit_batchimport').modal('hide');
        });
        $('#dialog_audit_batchimport').modal();
        </script>
     	"""
        return html + javascript

    @expose()
    def get_batch_import_error_table(self, *args, **kwargs):
        dbase_query = self.get_active_batchimporterror_list(*args, **kwargs)
        outputlist = []
        for item in dbase_query:
            outputlist.append({
                'added' : item.added,
                'message' : item.message,
                             })
            #outputlist.append({
            #    'added' : item.added,
            #    'idnumber' : '',
            #    'member' : '',
            #    'description' : '',
            #    'price' : '',
            #    'payment' : '',
            #    'message' : item.message,
            #                 })
        dbcolumnlist=[
                'added',
                'message',
                    ]
        #dbcolumnlist=[
        #        'added',
        #        'idnumber',
        #        'member',
        #        'description',
        #        'price',
        #        'payment',
        #        'message',
        #            ]
        theadlist=[
                'Date',
                'Error',
                ]
        #theadlist=[
        #        'Date',
        #        'ID Number',
        #        'Member',
        #        'Description',
        #        'Price',
        #        'Payment',
        #        'Error',
        #        ]
        return build_html_table(outputlist, dbcolumnlist, theadlist, "batchimporterror_table")

    @expose('rocket.templates.generic')
    def errors(self, *args, **kwargs):
        batch_import_id = kwargs.get('batch_import_id', None)
        if not batch_import_id: redirect('/batchimport/index')
        batch_import_error_table = self.get_batch_import_error_table(**kwargs)
        html = f"""
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                <div class="card-header">
                    <div class="row d-flex">
                        <div class="col-md-6">
                            <h4 class="card-title">Batch Import Errors</h4>
                        </div>
                        <div class="col-md-6 text-right">
                            <button class="btn btn btn-primary batchimport_back">Back to Batch Imports</button>
                            <button class="btn btn-primary">Export to Excel</button>
                        </div>
                    </div>
                </div>
                <div class="card-body">
                    <div id='div_error_table' class="table-responsive">
                        {batch_import_error_table}
                    </div>
                </div>
                </div>
            </div>
            <style>
                #div_error_table {{
                    max-height: 550px;
                    overflow-y: auto;
                }};
            </style>
        """
        javascript = """
        $('.batchimport_back').click(function(){
            $.redirect('/batchimport/index');
        });
     	"""
        title = "Batch Import Errors"
        return dict(title=title, html=html, javascript=javascript)

    @expose()
    def get_batchimport_by_id(self, *args, **kwargs):
        usernow = request.identity.get('user', {})
        return DBSession.query(BatchImport). \
            filter(BatchImport.id==kwargs.get('batch_import_id', None)). \
            first()

    @expose()
    def get_active_batchimport_list(self, *args, **kwargs):
        usernow = request.identity.get('user', {})
        kwargs['searchkey'] = SEARCHKEY
        searchphrase = COMMON.get_searchphrase(**kwargs).lower()
        if searchphrase:
            kwargs['searchphrase'] = searchphrase
            groupidlist = []
            importtypelist = [x.value for x in ImportType if searchphrase in str(x.name).lower()]
            dbase_query = DBSession.query(BatchImport). \
                filter(or_(
                    BatchImport.import_type_id.in_(importtypelist),
                    BatchImport.group_id.in_(groupidlist),
                )). \
                order_by(desc(BatchImport.id)). \
                limit(LIMIT)
        else:
            dbase_query = DBSession.query(BatchImport). \
                order_by(desc(BatchImport.id)). \
                limit(LIMIT)
        return dbase_query

    def get_selectbox_import_type(self, *args, **kwargs):
        import_type_list = []
        import_type_list = [record for record in BatchImportType.get_all('id') if record.name.lower() != 'default']
        kwargs['outputlist'] = [{'name': m.name, 'id': m.id} for m in import_type_list]
        return create_selectbox_html(**kwargs)

    def get_selectbox_import_type(self, *args, **kwargs):
        import_type_list = []
        import_type_list = [record for record in BatchImportType.get_all('id') if record.name.lower() != 'default']
        kwargs['outputlist'] = [{'name': m.name, 'id': m.id} for m in import_type_list]
        return create_selectbox_html(**kwargs)

    @expose()
    def handle_file_upload(self, *args, **kwargs):
        usernow = request.identity.get('user', {})
        kwargs['user_id'] = usernow.id
        kwargs['upload_dir'] = EXCEL_DIRNAME
        kwargs['size_limit'] = 256000000 # 256 MB
        kwargs['allowed_extensions'] = ['.xls', '.xlsx', '.ods']
        uploader = FileUploader(**kwargs)
        return uploader.handle_file_upload()

    @expose()
    def start_new_batch_import(self, *args, **kwargs):
        import_type = str_to_int(kwargs.get('import_type_id', None))
        if not import_type: return ''
        filename = kwargs.get('filename', None)
        if not filename: return ''
        member = TYPEUTIL.get_id_of_name('batch_import_type', 'member')
        family = TYPEUTIL.get_id_of_name('batch_import_type', 'family')
        purchase = TYPEUTIL.get_id_of_name('batch_import_type', 'purchase')
        usernow = request.identity.get('user', {})
        if import_type == member:
            return MemberImport(**kwargs).start_import()

        if import_type == purchase:
            return PurchaseImport(**kwargs).start_import()

        return ''

        if hasattr(self, 'running_import'): return "Already Importing"
        import_type = str_to_int(kwargs.get('import_type_id', None))
        if not import_type: return ''
        filename = kwargs.get('filename', None)
        if not filename: return ''
        member = TYPEUTIL.get_id_of_name('batch_import_type', 'member')
        family = TYPEUTIL.get_id_of_name('batch_import_type', 'family')
        purchase = TYPEUTIL.get_id_of_name('batch_import_type', 'purchase')
        usernow = request.identity.get('user', {})
        if import_type == member:
            kwargs['import_type_id'] = member
            kwargs['user_id'] = usernow.id
            kwargs['session'] = DBSession
            kwargs['language_id'] = 1
            kwargs['language_type_id'] = 1
            member_import = MemberImport(kwargs)
            self.running_import = member_import
            member_import.start_import()
            #CallToBatchImport(filename, import_type).run_batch_import()
        if import_type == family:
            print('Placeholder start the family import')
        if import_type == purchase:
            print('Placeholder start the purchase import')
        return ''

    @expose()
    def download_template(self, *args, **kwargs):
        import_type_id = str_to_int(kwargs.get('import_type_id', None))
        if not import_type_id: return ''
        member = TYPEUTIL.get_id_of_name('batch_import_type', 'member')
        family = TYPEUTIL.get_id_of_name('batch_import_type', 'family')
        purchase = TYPEUTIL.get_id_of_name('batch_import_type', 'purchase')
        if import_type_id  == member: filename = 'Member Import Template.xlsx'
        elif import_type_id == purchase: filename = 'Policy Import Template.xlsx'
        elif import_type_id == family: filename = 'Family Import Template.xlsx'
        else: filename = None
        filepath = os.path.join(EXCEL_DIRNAME, str(filename))
        if not os.path.exists(filepath): return ''
        response.headers["Content-Type"] = 'application/vnd.ms-excel'
        response.headers["Content-Disposition"] = 'attachment; filename="'+filename+'"'
        filecontent = FileApp(filepath)
        return use_wsgi_app(filecontent)

    @expose()
    def get_active_batchimportaudit_list(self, *args, **kwargs):
        usernow = request.identity.get('user', {})
        searchphrase = kwargs.get('searchphrase', None)
        batch_import_id = kwargs.get('batch_import_id', None)
        if searchphrase:
            dbase_query = DBSession.query(BatchImportAudit). \
                filter(BatchImportAudit.audit.like(searchphrase)). \
                order_by(asc(BatchImportAudit.audit)). \
                limit(LIMIT)
        elif batch_import_id:
            dbase_query = DBSession.query(BatchImportAudit). \
                filter(BatchImportAudit.batch_import_id==batch_import_id). \
                order_by(desc(BatchImportAudit.id)). \
                all()
        else:
            dbase_query = DBSession.query(BatchImportAudit). \
                order_by(asc(BatchImportAudit.id)). \
                limit(LIMIT)
        return dbase_query

    @expose()
    def get_active_batchimporterror_list(self, *args, **kwargs):
        usernow = request.identity.get('user', {})
        batch_import_id = kwargs.get('batch_import_id', None)
        if batch_import_id:
            dbase_query = DBSession.query(BatchImportError). \
                filter(BatchImportError.batch_import_id==batch_import_id). \
                order_by(desc(BatchImportError.id)). \
                all()
        else:
            dbase_query = DBSession.query(BatchImportError). \
                order_by(asc(BatchImportError.id)). \
                limit(LIMIT)
        return dbase_query

    @expose()
    def restart_batch_import(self, *args, **kwargs):
        batch_import_id = str_to_int(kwargs.get('batch_import_id', None))
        import_type = str_to_int(kwargs.get('import_type_id', None))
        if not batch_import_id: return ''
        batchimport = BatchImport.by_id(batch_import_id)
        if not batchimport: return ''
        if batchimport.import_type_id == ImportType.Member.value:
            MemberImportRecovery(**kwargs).restart_import()
        if import_type == ImportType.Family.value:
            return FamilyImport(**kwargs).restart_import()
        if batchimport.import_type_id == ImportType.Purchase.value:
            PurchaseImportRecovery(**kwargs).restart_import()
        return ''
예제 #11
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)
예제 #12
0
파일: precondition.py 프로젝트: todun/ksweb
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': WorkspaceExistValidator(required=True)})
    def index(self, workspace, **kw):
        return dict(
            page='precondition-index',
            fields={
                'columns_name': [l_('Label'), l_('Type'), l_('Owner'), l_('Id')],
                'fields_name': 'title type owner hash'.split()
            },
            entities=Precondition.available_for_user(request.identity['user']._id, workspace=workspace),
            actions_content=[l_('New Output'),l_('New QA')],
            workspace=workspace
        )

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

        #  Insert workspace name into res
        for e in res:
            e['workspace_name'] = Workspace.query.get(_id=ObjectId(e['_id'])).name

        return dict(precond=res)

    @expose('json')
    def available_preconditions(self, workspace=None):
        preconditions = Precondition.available_for_user(request.identity['user']._id, workspace=workspace).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):
        precondition = Precondition.query.get(_id=ObjectId(id))
        return dict(qas=precondition.response_interested)

    @expose('json')
    @validate({'workspace': WorkspaceExistValidator(required=True)})
    def mark_as_read(self, workspace):
        Precondition.mark_as_read(request.identity['user']._id, workspace)

    @expose('json')
    def open(self, _id):
        if not _id:
            tg.flash('The precondition you are looking for, does not exist')
            redirect()
        p = Precondition.query.get(_id=ObjectId(_id))
        redirect('/%s/edit' % (p.entity), params=dict(_id=p._id, workspace=p._workspace))
예제 #13
0
class RootController(BaseController):
    """
    The root controller for the ksweb application.

    All the other controllers and WSGI applications should be mounted on this
    controller. For example::

        panel = ControlPanelController()
        another_app = AnotherWSGIApplication()

    Keep in mind that WSGI applications shouldn't be mounted directly: They
    must be wrapped around with :class:`tg.controllers.WSGIAppController`.

    """
    admin = AdminController(model, None, config_type=TGAdminConfig)
    qa = QaController()
    precondition = PreconditionController()
    category = CategoryController()
    output = OutputController()
    document = DocumentController()
    questionary = QuestionaryController()
    resolve = ResolveController()
    output_plus = OutputPlusController()

    error = ErrorController()

    @expose('ksweb.templates.index')
    def index(self):
        if predicates.has_any_permission('manage', 'lawyer'):
            redirect('/start')
        return dict()

    @expose('ksweb.templates.questionary.index')
    @paginate('entities',
              items_per_page=int(config.get('pagination.items_per_page')))
    def dashboard(self, share_id):
        user = model.User.query.find({'_id': ObjectId(share_id)}).first()

        if not user:
            response.status_code = 403
            flash(_('You are not allowed to operate in this page'))
            return dict()

        entities = model.Questionary.query.find({
            '$or': [{
                '_user': ObjectId(user._id)
            }, {
                '_owner': ObjectId(user._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=None,
            show_sidebar=False,
            share_id=share_id)

    @decode_params('json')
    @expose('json')
    def become_editor_from_user(self, **kw):
        user = model.User.query.find({'_id': ObjectId(kw['share_id'])}).first()
        if user and not user.password:
            user.password = kw['password']
            user.user_name = kw['username']
            group = model.Group.query.find({'group_name': 'lawyer'}).first()
            user.groups = [group]
        return dict()

    @expose('ksweb.templates.start')
    @require(
        predicates.has_any_permission('manage',
                                      'lawyer',
                                      msg=l_('Only for admin or lawyer')))
    def start(self):
        user = request.identity['user']
        categories = model.Category.per_user(user._id)
        return dict(page='index',
                    user=user,
                    workspaces=categories,
                    show_sidebar=False)

    @expose('ksweb.templates.welcome')
    @require(
        predicates.has_any_permission('manage',
                                      'lawyer',
                                      msg=l_('Only for admin or lawyer')))
    def welcome(self, workspace):
        user = request.identity['user']
        ws = model.Category.query.find({'_id': ObjectId(workspace)}).first()
        return dict(page='welcome',
                    user=user,
                    workspace=workspace,
                    ws=ws,
                    show_sidebar=True)

    @expose('ksweb.templates.terms')
    def terms(self):
        return dict()

    @expose('ksweb.templates.privacy')
    def privacy(self):
        return dict()

    @expose('ksweb.templates.legal')
    def legal(self):
        return dict()

    @expose('ksweb.templates.source')
    def source(self):
        return dict()

    @expose('ksweb.templates.login')
    def login(self, came_from=lurl('/'), failure=None, login=''):
        """Start the user login."""
        if failure is not None:
            if failure == 'user-not-found':
                flash(_('User not found'), 'error')
            elif failure == 'invalid-password':
                flash(_('Invalid Password'), 'error')
            elif failure == 'user-created':
                flash(_('User successfully created'))

        login_counter = request.environ.get('repoze.who.logins', 0)
        if failure is None and login_counter > 0:
            flash(_('Wrong credentials'), 'warning')
        return dict(page='login',
                    login_counter=str(login_counter),
                    came_from=came_from,
                    login=login)

    @expose()
    def post_login(self, came_from=lurl('/')):
        """
        Redirect the user to the initially requested page on successful
        authentication or redirect her back to the login page if login failed.

        """
        if not request.identity:
            login_counter = request.environ.get('repoze.who.logins', 0) + 1
            redirect('/login',
                     params=dict(came_from=came_from, __logins=login_counter))
        userid = request.identity['repoze.who.userid']
        flash(_('Welcome back, %s!') % userid)

        # Do not use tg.redirect with tg.url as it will add the mountpoint
        # of the application twice.
        return HTTPFound(location=came_from)

    @expose()
    def post_logout(self, came_from=lurl('/')):
        """
        Redirect the user to the initially requested page on logout and say
        goodbye as well.

        """
        flash(_('We hope to see you soon!'))
        return HTTPFound(location=came_from)
예제 #14
0
파일: qa.py 프로젝트: 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
예제 #15
0
class RootController(BaseController):
    admin = AdminController(model, None, config_type=TGAdminConfig)
    qa = QaController()
    precondition = PreconditionController()
    workspace = WorkspaceController()
    output = OutputController()
    document = DocumentController()
    questionary = FormController()
    resolve = ResolveController()
    output_plus = OutputPlusController()

    error = ErrorController()

    @expose('ksweb.templates.index')
    def index(self):
        if predicates.has_any_permission('manage', 'lawyer'):
            redirect('/start')
        return dict()

    @expose('ksweb.templates.questionary.index')
    @paginate('entities',
              items_per_page=int(config.get('pagination.items_per_page')))
    def dashboard(self, share_id):
        user = model.User.query.find({'_id': ObjectId(share_id)}).first()

        if not user:
            response.status_code = 403
            flash(_('You are not allowed to operate in this page'))
            redirect('/start')

        entities = model.Questionary.query.find({
            '$or': [{
                '_user': ObjectId(user._id)
            }, {
                '_owner': ObjectId(user._id)
            }]
        }).sort('title')

        if not entities.count():
            flash(
                _('You don\'t have any form associated to %s' %
                  user.email_address))
            redirect('/start')

        auth_force_login(user.user_name)
        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=None,
            show_sidebar=False,
            share_id=share_id)

    @decode_params('json')
    @expose('json')
    def become_editor_from_user(self, **kw):
        user = model.User.query.find({'_id': ObjectId(kw['share_id'])}).first()
        if user and not user.password:
            user.password = kw['password']
            user.user_name = kw['username']
            group = model.Group.query.find({'group_name': 'lawyer'}).first()
            user.groups = [group]
        return dict()

    @expose('ksweb.templates.start')
    @require(
        predicates.has_any_permission('manage',
                                      'lawyer',
                                      msg=l_('Only for admin or lawyer')))
    def start(self):
        user = request.identity['user']
        categories = model.Workspace.per_user(user._id)
        return dict(page='index',
                    user=user,
                    workspaces=categories,
                    show_sidebar=False)

    @expose('ksweb.templates.welcome')
    @require(
        predicates.has_any_permission('manage',
                                      'lawyer',
                                      msg=l_('Only for admin or lawyer')))
    @validate({'workspace': Convert(ObjectId, 'must be a valid ObjectId')},
              error_handler=ksweb_error_handler)
    def welcome(self, workspace):
        user = request.identity['user']
        ws = model.Workspace.query.find({'_id': ObjectId(workspace)}).first()
        return dict(page='welcome',
                    user=user,
                    workspace=workspace,
                    ws=ws,
                    show_sidebar=True)

    @expose('json')
    @require(
        predicates.has_any_permission('manage',
                                      'lawyer',
                                      msg=l_('Only for admin or lawyer')))
    def entity(self, _id):
        entity = entity_from_hash(_id)
        if not entity:
            entity = entity_from_id(_id)
        if entity:
            redirect(entity.url)

        abort(404)

    @expose('ksweb.templates.terms')
    def terms(self):
        return dict()

    @expose('ksweb.templates.privacy')
    def privacy(self):
        return dict()

    @expose('ksweb.templates.legal')
    def legal(self):
        return dict()

    @expose('ksweb.templates.source')
    def source(self):
        return dict()

    @expose('ksweb.templates.login')
    def login(self, came_from=lurl('/'), failure=None, login=''):
        if failure is not None:
            if failure == 'user-not-found':
                flash(_('User not found'), 'error')
            elif failure == 'invalid-password':
                flash(_('Invalid Password'), 'error')
            elif failure == 'user-created':
                flash(_('User successfully created'))

        login_counter = request.environ.get('repoze.who.logins', 0)
        if failure is None and login_counter > 0:
            flash(_('Wrong credentials'), 'warning')
        return dict(page='login',
                    login_counter=str(login_counter),
                    came_from=came_from,
                    login=login)

    @expose()
    def post_login(self, came_from=lurl('/')):
        if not request.identity:
            login_counter = request.environ.get('repoze.who.logins', 0) + 1
            redirect('/login',
                     params=dict(came_from=came_from, __logins=login_counter))
        userid = request.identity['repoze.who.userid']
        flash(_('Welcome back, %s!') % userid)
        return HTTPFound(location=came_from)

    @expose()
    def post_logout(self, came_from=lurl('/')):
        flash(_('We hope to see you soon!'))
        return HTTPFound(location=came_from)
예제 #16
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)
예제 #17
0
 def index(self):
     if predicates.has_any_permission('manage', 'lawyer'):
         redirect('/start')
     return dict()
예제 #18
0
 def test_user_has_one_permission(self):
     environ = make_environ('gustavo',
                            permissions=['watch-tv', 'party', 'eat'])
     p = predicates.has_any_permission('party', 'scream')
     self.eval_met_predicate(p, environ)
예제 #19
0
파일: root.py 프로젝트: puria/ksweb
class RootController(BaseController):
    admin = AdminController(model, None, config_type=TGAdminConfig)
    qa = QaController()
    precondition = PreconditionController()
    workspace = WorkspaceController()
    output = OutputController()
    document = DocumentController()
    questionary = FormController()
    resolve = ResolveController()
    output_plus = OutputPlusController()

    error = ErrorController()

    @expose("ksweb.templates.index")
    def index(self):
        if predicates.has_any_permission("manage", "lawyer"):
            redirect("/start")
        return dict()

    @expose("ksweb.templates.questionary.index")
    @paginate("entities",
              items_per_page=int(config.get("pagination.items_per_page")))
    def dashboard(self, share_id):
        user = model.User.query.find({"_id": ObjectId(share_id)}).first()

        if not user:
            response.status_code = 403
            flash(_("You are not allowed to operate in this page"))
            redirect("/start")

        entities = model.Questionary.query.find({
            "$or": [{
                "_user": ObjectId(user._id)
            }, {
                "_owner": ObjectId(user._id)
            }]
        }).sort("title")

        if not entities.count():
            flash(
                _("You don't have any form associated to %s" %
                  user.email_address))
            redirect("/start")

        auth_force_login(user.user_name)
        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=None,
            show_sidebar=False,
            share_id=share_id,
        )

    @decode_params("json")
    @expose("json")
    def become_editor_from_user(self, **kw):
        user = model.User.query.find({"_id": ObjectId(kw["share_id"])}).first()
        if user and not user.password:
            user.password = kw["password"]
            user.user_name = kw["username"]
            group = model.Group.query.find({"group_name": "lawyer"}).first()
            user.groups = [group]
        return dict()

    @expose("ksweb.templates.start")
    @require(
        predicates.has_any_permission("manage",
                                      "lawyer",
                                      msg=l_("Only for admin or lawyer")))
    def start(self):
        user = request.identity["user"]
        categories = model.Workspace.per_user(user._id)
        return dict(page="index",
                    user=user,
                    workspaces=categories,
                    show_sidebar=False)

    @expose("ksweb.templates.welcome")
    @require(
        predicates.has_any_permission("manage",
                                      "lawyer",
                                      msg=l_("Only for admin or lawyer")))
    @validate(
        {"workspace": Convert(ObjectId, "must be a valid ObjectId")},
        error_handler=ksweb_error_handler,
    )
    def welcome(self, workspace):
        user = request.identity["user"]
        ws = model.Workspace.query.find({"_id": ObjectId(workspace)}).first()
        return dict(page="welcome",
                    user=user,
                    workspace=workspace,
                    ws=ws,
                    show_sidebar=True)

    @expose("json")
    @require(
        predicates.has_any_permission("manage",
                                      "lawyer",
                                      msg=l_("Only for admin or lawyer")))
    def entity(self, _id):
        entity = entity_from_hash(_id)
        if not entity:
            entity = entity_from_id(_id)
        if entity:
            redirect(entity.url)

        abort(404)

    @expose("ksweb.templates.terms")
    def terms(self):
        return dict()

    @expose("ksweb.templates.privacy")
    def privacy(self):
        return dict()

    @expose("ksweb.templates.legal")
    def legal(self):
        return dict()

    @expose("ksweb.templates.source")
    def source(self):
        return dict()

    @expose("ksweb.templates.login")
    def login(self, came_from=lurl("/"), failure=None, login=""):
        if failure is not None:
            if failure == "user-not-found":
                flash(_("User not found"), "error")
            elif failure == "invalid-password":
                flash(_("Invalid Password"), "error")
            elif failure == "user-created":
                flash(_("User successfully created"))

        login_counter = request.environ.get("repoze.who.logins", 0)
        if failure is None and login_counter > 0:
            flash(_("Wrong credentials"), "warning")
        return dict(
            page="login",
            login_counter=str(login_counter),
            came_from=came_from,
            login=login,
        )

    @expose()
    def post_login(self, came_from=lurl("/")):
        if not request.identity:
            login_counter = request.environ.get("repoze.who.logins", 0) + 1
            redirect("/login",
                     params=dict(came_from=came_from, __logins=login_counter))
        userid = request.identity["repoze.who.userid"]
        flash(_("Welcome back, %s!") % userid)
        return HTTPFound(location=came_from)

    @expose()
    def post_logout(self, came_from=lurl("/")):
        flash(_("We hope to see you soon!"))
        return HTTPFound(location=came_from)