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')
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')
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())
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')
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)))
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
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)
def index(self): if predicates.has_any_permission("manage", "lawyer"): redirect("/start") return dict()
class OutputController(RestController): def _validate_precondition_with_qa(self, precondition, content): if not precondition: return dict(errors={'content': _('Filter not found')}) # Check content precondition element precond = model.Precondition.query.find({ '_id': ObjectId(precondition) }).first() related_qa = precond.response_interested # Check elem['content'] contain the obj id of the related for elem in content: if elem['type'] == 'qa_response': if elem['content'] not in related_qa.keys(): response.status_code = 412 return dict( errors={ 'content': _('The question %s is not related to the filter') % elem['title'] }) return dict() def _before(self, *args, **kw): tmpl_context.sidebar_section = "outputs" tmpl_context.id_obj = kw.get('_id') allow_only = predicates.has_any_permission( 'manage', 'lawyer', msg=l_('Only for admin or lawyer')) @expose('ksweb.templates.output.index') @paginate('entities', items_per_page=int(tg.config.get('pagination.items_per_page'))) @validate({'workspace': CategoryExistValidator(required=True)}) def get_all(self, workspace, **kw): return dict(page='output-index', fields={ 'columns_name': [_('Label'), _('Filter'), _('Content')], 'fields_name': ['title', 'precondition', 'content'] }, entities=model.Output.output_available_for_user( request.identity['user']._id, workspace), actions=False, workspace=workspace) @expose('json') @expose('ksweb.templates.output.new') @validate({'workspace': CategoryExistValidator(required=True)}) def new(self, workspace, **kw): tmpl_context.sidebar_output = "output-new" return dict(output={'_precondition': kw.get('precondition_id', None)}, workspace=workspace, errors=None) @decode_params('json') @expose('json') @validate( { 'title': StringLengthValidator(min=2), 'content': OutputContentValidator(), 'ks_editor': StringLengthValidator(min=2), 'category': CategoryExistValidator(required=True), 'precondition': PreconditionExistValidator(), }, error_handler=validation_errors_response) def post(self, title, content, category, precondition, **kw): content = content or [] # Check content precondition element error = self._validate_precondition_with_qa(precondition, content) if error: return error user = request.identity['user'] model.Output(_owner=user._id, _category=ObjectId(category), _precondition=ObjectId(precondition), title=title, content=content, public=True, visible=True, html=kw['ks_editor']) return dict(errors=None) @expose('json') @decode_params('json') @validate( { '_id': OutputExistValidator(required=True), 'title': StringLengthValidator(min=2), 'content': OutputContentValidator(), 'category': CategoryExistValidator(required=True), 'precondition': PreconditionExistValidator(), }, error_handler=validation_errors_response) @require( CanManageEntityOwner( msg=l_(u'You are not allowed to edit this output.'), field='_id', entity_model=model.Output)) def put(self, _id, title, content, category, precondition, **kw): content = content or [] # Check content precondition element error = self._validate_precondition_with_qa(precondition, content) if error: return error check = self.get_related_entities(_id) if check.get("entities"): entity = dict(_id=_id, title=title, content=content, _category=category, _precondition=precondition, entity='output', html=kw['ks_editor']) session[ 'entity'] = entity # overwrite always same key for avoiding conflicts session.save() return dict(redirect_url=tg.url('/resolve', params=dict(workspace=category))) output = model.Output.query.find({'_id': ObjectId(_id)}).first() output.title = title output._category = ObjectId(category) output._precondition = ObjectId(precondition) output.content = content output.html = kw['ks_editor'] return dict(errors=None, redirect_url=None) @expose('ksweb.templates.output.new') @validate( { '_id': OutputExistValidator(required=True), 'workspace': CategoryExistValidator(required=True), }, error_handler=validation_errors_response) @require( CanManageEntityOwner( msg=l_(u'You are not allowed to edit this output.'), field='_id', entity_model=model.Output)) def edit(self, _id, workspace, **kw): output = model.Output.query.find({ '_id': ObjectId(_id), '_category': ObjectId(workspace) }).first() tmpl_context.sidebar_output = "output-edit" return dict(output=output, workspace=workspace, errors=None) @expose('json') def sidebar_output(self, _id=None, workspace=None): #pragma: no cover res = list( model.Output.query.aggregate([{ '$match': { '_owner': request.identity['user']._id, '_id': { '$ne': ObjectId(_id) }, 'visible': True, '_category': ObjectId(workspace) } }, { '$group': { '_id': '$_category', 'output': { '$push': "$$ROOT", } } }])) # Insert category name into res for e in res: e['category_name'] = model.Category.query.get( _id=ObjectId(e['_id'])).name return dict(outputs=res) @expose('json') @decode_params('json') @validate({ '_id': OutputExistValidator(required=True), }, error_handler=validation_errors_response) def human_readable_details(self, _id, **kw): output = model.Output.query.get(_id=ObjectId(_id)) return dict( output={ '_id': output._id, 'title': output.title, 'content': output.human_readbale_content, 'human_readbale_content': output.human_readbale_content, '_owner': output._owner, 'owner': output.owner.display_name, '_precondition': output._precondition, 'precondition': output.precondition.title, '_category': output._category, 'category': output.category.name, 'public': output.public, 'visible': output.visible, 'created_at': output.created_at }) @decode_params('json') @expose('json') def get_related_entities(self, _id): """ This method return ALL entities (Output, Document) that have inside a `content.content` the given _id :param _id: :return: """ output_related = model.Output.query.find({ "content.type": "output", "content.content": _id }).all() documents_related = model.Document.query.find({ "content.type": "output", "content.content": _id }).all() entities = list(output_related + documents_related) return dict(entities=entities, len=len(entities))
class 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 ''
class PreconditionController(BaseController): allow_only = predicates.has_any_permission('manage', 'lawyer', msg=l_('Only for admin or lawyer')) def _before(self, *args, **kw): tmpl_context.sidebar_section = "preconditions" simple = PreconditionSimpleController() advanced = PreconditionAdvancedController() @expose('ksweb.templates.precondition.index') @paginate('entities', items_per_page=int(tg.config.get('pagination.items_per_page'))) @validate({'workspace': CategoryExistValidator(required=True)}) def index(self, workspace, **kw): return dict( page='precondition-index', fields={ 'columns_name': [l_('Label'), l_('Type'), l_('Owner')], 'fields_name': ['title', 'type', 'owner'] }, entities=model.Precondition.precondition_available_for_user(request.identity['user']._id, workspace=workspace), actions_content=[l_('New Output'),l_('New Q/A')], workspace=workspace ) @expose('json') def sidebar_precondition(self, workspace): #pragma: no cover res = list(model.Precondition.query.aggregate([ { '$match': { '_owner': request.identity['user']._id, # 'visible': True '_category': ObjectId(workspace) } }, { '$group': { '_id': '$_category', 'precondition': {'$push': "$$ROOT",} } } ])) # Insert category name into res for e in res: e['category_name'] = model.Category.query.get(_id=ObjectId(e['_id'])).name return dict(precond=res) @expose('json') def available_preconditions(self, workspace=None): preconditions = Precondition.query.find({'_owner': request.identity['user']._id, 'visible': True, '_category': ObjectId(workspace)}).sort('title').all() return dict(preconditions=preconditions) @expose('json') @decode_params('json') @validate({ 'id': PreconditionExistValidator(required=True), }, error_handler=validation_errors_response) def qa_precondition(self, id, **kw): print(ObjectId(id)) precondition = model.Precondition.query.get(_id=ObjectId(id)) print(precondition.response_interested) return dict(qas=precondition.response_interested)
class 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))
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)
class QaController(RestController): def _before(self, *args, **kw): tmpl_context.sidebar_section = "qas" allow_only = predicates.has_any_permission( 'manage', 'lawyer', msg=l_('Only for admin or lawyer')) @expose('ksweb.templates.qa.index') @paginate('entities', items_per_page=int(tg.config.get('pagination.items_per_page'))) @validate({ 'workspace': CategoryExistValidator(required=True), }, error_handler=validation_errors_response) def get_all(self, workspace=None, **kw): return dict(page='qa-index', fields={ 'columns_name': [_('Label'), _('Question'), _('Filter')], 'fields_name': ['title', 'question', 'parent_precondition'] }, entities=model.Qa.qa_available_for_user( request.identity['user']._id, workspace), actions=False, workspace=workspace) @expose('json') @validate({ 'id': QAExistValidator(required=True), }, error_handler=validation_errors_response) def get_one(self, id, **kw): qa = model.Qa.query.find({ '_id': ObjectId(id), '_owner': request.identity['user']._id }).first() return dict(qa=qa) @expose('json') @validate({'workspace': CategoryExistValidator(required=True)}) def get_single_or_multi_question(self, workspace): questions = model.Qa.query.find({ 'type': { '$in': ['single', 'multi'] }, '_owner': request.identity['user']._id, '_category': ObjectId(workspace) }).all() return dict(questions=[{ '_id': qa._id, 'title': qa.title } for qa in questions]) @expose('json') @expose('ksweb.templates.qa.new') @validate({ 'workspace': CategoryExistValidator(required=True), }) def new(self, workspace, **kw): return dict(errors=None, workspace=workspace, referrer=kw.get('referrer'), qa={ 'question': kw.get('question_content', None), 'title': kw.get('question_title', None), '_parent_precondition': kw.get('precondition_id', None) }) @decode_params('json') @expose('json') @validate( { 'title': StringLengthValidator(min=2), 'category': CategoryExistValidator(required=True), 'question': StringLengthValidator(min=2), 'tooltip': StringLengthValidator(min=0, max=100), 'link': StringLengthValidator(min=0, max=100), 'answer_type': OneOfValidator(values=model.Qa.QA_TYPE, required=True), 'precondition': PreconditionExistValidator(required=False), }, error_handler=validation_errors_response) def post(self, title, category, question, tooltip, link, answer_type, precondition=None, answers=None, **kw): if not self._are_answers_valid(answer_type, answers): response.status_code = 412 return dict( errors={'answers': _('Please add at least one more answer')}) user = request.identity['user'] qa = model.Qa(_owner=user._id, _category=ObjectId(category), _parent_precondition=ObjectId(precondition) if precondition else None, title=title, question=question, tooltip=tooltip, link=link, type=answer_type, answers=answers, public=True, visible=True) self._autofill_qa_filters(qa) return dict(errors=None, _id=ObjectId(qa._id)) @decode_params('json') @expose('json') @validate( { '_id': QAExistValidator(required=True), 'title': StringLengthValidator(min=2), 'category': CategoryExistValidator(required=True), 'question': StringLengthValidator(min=2), 'tooltip': StringLengthValidator(min=0, max=100), 'link': StringLengthValidator(min=0, max=100), 'answer_type': OneOfValidator(values=model.Qa.QA_TYPE, required=True), 'precondition': PreconditionExistValidator(required=False), }, error_handler=validation_errors_response) def put(self, _id, title, category, question, tooltip, link, answer_type, precondition=None, answers=None, **kw): if not self._are_answers_valid(answer_type, answers): response.status_code = 412 return dict( errors={'answers': _('Please add at least one more answer')}) check = self.get_related_entities(_id) if check.get("entities"): entity = dict(_id=_id, _category=category, title=title, entity='qa', question=question, tooltip=tooltip, link=link, type=answer_type, _parent_precondition=precondition, answers=answers) session.data_serializer = 'pickle' session[ 'entity'] = entity # overwrite always same key for avoiding conflicts session.save() return dict(redirect_url=tg.url('/resolve', params=dict(workspace=category))) qa = model.Qa.query.get(_id=ObjectId(_id)) qa._category = ObjectId(category) qa._parent_precondition = to_object_id(precondition) qa.title = title qa.question = question qa.tooltip = tooltip qa.question = question qa.link = link qa.type = answer_type qa.answers = answers self._autofill_qa_filters(qa) return dict(errors=None) @expose('ksweb.templates.qa.new') @validate({'_id': QAExistValidator(model=True)}, error_handler=validation_errors_response) @require( CanManageEntityOwner(msg=l_(u'You can not edit this Q/A'), field='_id', entity_model=model.Qa)) def edit(self, _id, workspace=None, **kw): ws = model.Category.query.find({'_id': ObjectId(workspace)}).first() if not ws: return tg.abort(404) qa = model.Qa.query.find({'_id': ObjectId(_id)}).first() return dict(qa=qa, workspace=ws._id, errors=None) @expose('json') @decode_params('json') @validate({ '_id': QAExistValidator(required=True), }, error_handler=validation_errors_response) def human_readable_details(self, _id, **kw): qa = model.Qa.query.find({'_id': ObjectId(_id)}).first() return dict(qa=qa) @decode_params('json') @expose('json') def get_related_entities(self, _id): """ This method return ALL entities (Precondition simple) that have inside the given _id :param _id: :return: """ preconditions_related = model.Precondition.query.find({ 'type': 'simple', 'condition': ObjectId(_id) }) entities = list(preconditions_related) return {'entities': entities, 'len': len(entities)} def _autofill_qa_filters(self, qa): user = request.identity['user'] if qa.type == 'text': # model.Qa.QA_TYPE[0] model.Precondition(_owner=user._id, _category=ObjectId(qa._category), title=qa.title + _(' -> ANSWERED'), type='simple', condition=[qa._id, '']) else: base_precond = [] for answer in qa.answers: prec = model.Precondition( _owner=user._id, _category=ObjectId(qa._category), title=qa.title + ' -> %s' % answer, type='simple', condition=[qa._id, answer], ) base_precond.append(prec) condition = [] for prc in base_precond[:-1]: condition.append(prc._id) condition.append('or') condition.append(base_precond[-1]._id) created_precondition = model.Precondition( _owner=user._id, _category=ObjectId(qa._category), title=qa.title + _(' -> ANSWERED'), type='advanced', condition=condition) def _are_answers_valid(self, answer_type, answers): if (answer_type == "single" and len(answers) < 2) or\ (answer_type == "multi" and len(answers) < 1): return False return True
class 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)
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)
def index(self): if predicates.has_any_permission('manage', 'lawyer'): redirect('/start') return dict()
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)