def check_access(): '''Check access rights / group: admin=full access, boss=users from same department, user. Returns SA Query object for selected CDRs ''' if in_any_group('admin', 'APPELS'): cdrs = DBSession.query(CDR) elif in_group('CDS'): # Find list of phones from the user's list of phones # user_phones -> departments -> phones phones = [] for p in request.identity['user'].phone: log.info('CDS phone %s -> department %s' % (p, p.department)) for d in [d.department for d in request.identity['user'].phone]: log.info('CDS department <%s>' % (d)) for p in d.phones: phones.append(p) src = [prefix_src + p.exten for p in phones] dst = [p.exten for p in phones] cdrs = DBSession.query(CDR).filter( (CDR.src.in_(src)) | (CDR.dst.in_(dst)) ) log.info('CDS phone <%s> -> source <%s>, destination <%s>' % ( request.identity['user'].phone, src, dst)) elif in_group('utilisateurs'): src = [prefix_src + p.exten for p in request.identity['user'].phone] dst = [p.exten for p in request.identity['user'].phone] cdrs = DBSession.query(CDR).filter( (CDR.src.in_(src)) | (CDR.dst.in_(dst)) ) else: flash(u'Accès interdit') redirect('/') return cdrs
def update_queues(self, last=0): ''' Function called on AJAX request made by template. Return when new updates available, or timeout ''' last = int(last) # Last template refresh (0 -> page just loaded) change = False u = DBSession.query(User).filter(User.user_name==request.identity['repoze.who.userid']).one() try: phone = u.phone[0].phone_id except: phone = None log.debug('User %s, phone_id=%s' % (u, phone)) queues = copy.deepcopy(Globals.asterisk.queues) members = copy.deepcopy(Globals.asterisk.members) # log.debug('Q BEFORE %s' % Globals.asterisk.queues) # log.debug('M BEFORE %s' % Globals.asterisk.members) for i in xrange(50): last_update = int(Globals.asterisk.last_queue_update) if last_update > last: break if queues != Globals.asterisk.queues or \ members != Globals.asterisk.members or last == 0: change = True break else: last = last_update sleep(1) log.debug(' * * * update_queues returns after sleeping %d sec, change=%s' % (i,change)) admin = False if in_group('admin'): queues = Globals.asterisk.queues admin = True else: queues = {} for q in Globals.asterisk.queues: if in_group('SV ' + q): queues[q] = Globals.asterisk.queues[q] admin = True elif in_group('AG ' + q): queues[q] = Globals.asterisk.queues[q] qq = [{'name': k, 'params': queues[k] } for k in sorted(queues, key=lambda x: int(queues[x]['Weight']), reverse=True) ] # log.debug('Q %s' % Globals.asterisk.queues) # log.debug('M %s' % Globals.asterisk.members) return dict(last=last_update, change=True, # XXX queues=qq, members=Globals.asterisk.members, admin=admin, my_name=u.ascii_name, my_phone=phone, my_groups=[g.group_name for g in u.groups])
def check_access(queues): '''Check access rigths to queues ''' if in_group('admin'): user_queues = queues else: user_queues = [] if type(queues)!=type([]): queues = [queues] for q in queues: if in_group('SV ' + q): user_queues.append(q) log.debug('User queues: %s' % user_queues) return user_queues
def edit(self, id=None, **kw): ''' Display edit user form ''' if not id: if 'user_id' in kw: id = kw['user_id'] else: id = request.identity['user'].user_id if not in_group('admin') and request.identity['user'].user_id != int(id): flash(u'Accès interdit !', 'error') redirect('/') u = DBSession.query(User).get(id) if not u: flash(u'Une erreur est survenue !', 'warning') log.info('user not found %d !' % id) redirect('/users/') try: ln = u.lastname fn = u.firstname except: ln = u.display_name fn = '' if u.phone: phone = u.phone[0].phone_id else: phone=None if in_group('admin'): groups = [g.group_id for g in u.groups] else: groups = ', '.join([g.group_name for g in u.groups]) v = {'user_id': u.user_id, 'user_name': u.user_name, 'firstname': fn, 'lastname': ln, 'email_address': u.email_address, 'fax': u.fax, 'voicemail': u.voicemail, 'email_voicemail': u.email_voicemail, 'pwd1': u.password, 'pwd2': u.password, 'phone_id': phone, 'groups': groups, '_method': 'PUT' } if in_group('admin'): tmpl_context.form = admin_edit_user_form else: tmpl_context.form = edit_user_form return dict(title = u'Modification utilisateur ' + u.user_name, debug='', values=v)
class RootController(TGController): custom_allow = CustomAllowOnly() smart_allow = SmartDenialAllowOnly() cp = ControlPanel() rest = DaRestController() mounted_app = WSGIAppController(wsgi_app, allow_only=is_user('gustavo')) @expose() def index(self): return "you're in the main page" @expose() @require(is_user('developer')) def commit(self): return 'you can commit' @expose('json:') @require(is_user('developer'), smart_denial=True) def smartabort(self): return {'key': 'value'} @expose() @require(in_group('managers')) @require(has_permission('commit')) def force_commit(self): return 'you can commit'
def get_all(self): ''' List all users ''' if not in_group('admin'): redirect( str(request.identity['user'].user_id) + '/edit') grid = MyJqGrid( id='grid', url='fetch', caption=u'Utilisateurs', colNames = [u'Action', u'Compte', u'Nom', u'email', u'Poste', u'Groupes'], colModel = [ { 'sortable': False, 'search': False, 'width': 80, 'align': 'center' }, { 'name': 'user_name', 'width': 80 }, { 'name': 'display_name', 'width': 120 }, { 'name': 'email_address', 'width': 180 }, { 'name': 'phone', 'width': 60, 'sortable': False, 'search': False }, { 'name': 'groups', 'width': 160, 'sortable': False, 'search': False } ], sortname = 'user_name', navbuttons_options = {'view': False, 'edit': False, 'add': True, 'del': False, 'search': True, 'refresh': True, 'addfunc': js_callback('add'), } ) tmpl_context.grid = grid tmpl_context.form = None tmpl_context.count = u'Total : %d utilisateurs' % DBSession.query(User).count() return dict( title=u'Liste des utilisateurs', debug='')
class RootController(TGController): calendar = CalendarController() event = EventController() @require(predicates.in_group('calendarevents')) @expose('calendarevents.templates.index') def index(self): return plug_redirect('calendarevents', '/calendar/list')
def update_params(self,d): q = DBSession.query(Phone) if not in_group('admin'): dptm = [p.department.dptm_id for p in request.identity['user'].phone] q = q.filter(Phone.department_id.in_(dptm)) q = q.order_by(Phone.exten) d['options'] = [(p.exten, p.exten) for p in q] SingleSelectField.update_params(self, d) return d
def update_params(self,d): opt_ext = [(p.exten, p.exten) for p in DBSession.query(Phone).order_by(Phone.exten)] if in_group('admin'): # help_text = u'Sélectionnez le poste interne ou le SVI destination du renvoi' opt_ivr = [(a.exten, a.name) for a in DBSession.query(Application).order_by(Application.name)] d['options'] = [(u'Postes', opt_ext), (u'SVI', opt_ivr)] else: d['options'] = opt_ext SingleSelectField.update_params(self, d) return d
def check_access(cdrs): '''Check access rights / group: admin=full access, boss=users from same department, user. Returns SA Query object for selected CDRs ''' if in_any_group('admin', 'DG', 'COMPTA'): return cdrs elif in_group('CDS'): # Find list of departments from the user's phones deps = [p.department.dptm_id for p in request.identity['user'].phone] log.info('CDS departments <%s>' % (deps)) cdrs = cdrs.filter(CDR.department.in_(deps)) elif in_group('Utilisateurs'): cdrs = cdrs.filter(CDR.user==request.identity['user'].user_id) else: flash(u'Accès interdit') redirect('/') return cdrs
class CalendarController(TGController): @expose('calendarevents.templates.calendar.calendar') @validate(dict(cal=SQLAEntityConverter(model.Calendar), start_from=DateParameterValidator()), error_handler=fail_with(404)) def _default(self, cal, view='month', start_from=None, **kw): if view not in ('month', 'basicWeek', 'basicDay', 'agendaWeek', 'agendaDay'): view = 'month' return dict(cal=cal, view=view, start_from=start_from) @expose('calendarevents.templates.calendar.events') @validate(dict(cal=SQLAEntityConverter(model.Calendar)), error_handler=fail_with(404)) def events(self, cal): return dict(cal=cal) @expose('calendarevents.templates.calendar.list') @require(predicates.in_group('calendarevents')) def list(self): calendar_list = DBSession.query(model.Calendar).all() return dict(calendar_list=calendar_list) @expose('calendarevents.templates.calendar.new') @require(predicates.in_group('calendarevents')) def new(self, **kw): return dict(form=new_calendar_form) @expose() @require(predicates.in_group('calendarevents')) @validate(new_calendar_form, error_handler=validated_handler(new)) def save(self, name, events_type): new_calendar = create_calendar(name=name, events_type=events_type) model.DBSession.flush() flash(_('Calendar successfully added')) return plug_redirect('calendarevents', '/calendar/%d' % new_calendar.uid)
class RootController(TGController): custom_allow = CustomAllowOnly() smart_allow = SmartDenialAllowOnly() cp = ControlPanel() rest = DaRestController() mounted_app = WSGIAppController(wsgi_app, allow_only=is_user('gustavo')) @expose() def index(self): return "you're in the main page" @expose() @require(is_user('developer')) def commit(self): return 'you can commit' @expose('json:') @require(is_user('developer'), smart_denial=True) def smartabort(self): return {'key': 'value'} @expose() def passthrough_abort(self): abort(403, passthrough='json') @expose() def passthrough_explicit(self): request.disable_auth_challenger() abort(403) @expose() @require(in_group('managers')) @require(has_permission('commit')) def force_commit(self): return 'you can commit' @expose() def login_logout(self, username, noidentifier='0'): if noidentifier == '1': request.environ['repoze.who.plugins'] = {} if username == 'logout': auth_force_logout() else: auth_force_login('%s:managers' % username) return 'OK'
def new(self, **kw): ''' Display new forward form ''' if in_any_group('admin', 'CDS'): tmpl_context.form = new_forward_cds_form log.debug('admin / CDS -> tmpl_context.form = new_forward_CDS_form') elif in_group('Renvoi externe'): tmpl_context.form = new_forward_external_form log.debug('tmpl_context.form = new_forward_external_form') else: tmpl_context.form = new_forward_form log.debug('tmpl_context.form = new_forward_form') return dict(title = u'Nouveau renvoi', debug='', values=None)
def fetch(self, page, rows, sidx='date', sord='asc', _search='false', searchOper=None, searchField=None, searchString=None, **kw): ''' Function called on AJAX request made by FlexGrid Fetch data from DB, return the list of rows + total + current page ''' # Try and use grid preference grid_rows = session.get('grid_rows', None) if rows=='-1': # Default value rows = grid_rows if grid_rows is not None else 25 # Save grid preference session['grid_rows'] = rows session.save() rows = int(rows) try: page = int(page) rows = int(rows) offset = (page-1) * rows except: offset = 0 page = 1 rows = 25 u = DBSession.query(User).filter(User.user_name==request.identity['repoze.who.userid']).one() fax = DBSession.query(Fax) if not in_group('admin'): fax = fax.filter(Fax.user_id==u.user_id) total = fax.count()/rows + 1 column = getattr(Fax, sidx) fax = fax.order_by(getattr(column,sord)()).offset(offset).limit(rows) rows = [ { 'id' : f.fax_id, 'cell': row(f) } for f in fax ] return dict(page=page, total=total, rows=rows)
def test_user_doesnt_belong_to_group(self): environ = make_environ('gustavo', ['developers', 'admins']) p = predicates.in_group('designers') self.eval_unmet_predicate( p, environ, 'The current user must belong to the group "designers"')
def validate(self, params, state): log.debug(params) f = new_forward_external_form if in_group('Renvoi externe') \ else new_forward_form return f.validate(params, state)
class ExtractionsController(BaseController): filter = ExtractionFilterController() @expose('etl.templates.extractions.index') @require(predicates.not_anonymous()) def index(self, **kw): categories = DBSession.query(app_model.Category).all() uncategorised = DBSession.query(Extraction).filter_by( category_id=None).all() categories += [Bunch(extractions=uncategorised, name="No Category")] return dict(categories=categories, has_validation_errors=request.validation.errors, new_form=CreateExtractionForm) @expose() @require(predicates.in_group('managers')) @validate(CreateExtractionForm, error_handler=index) def create(self, name, **kw): DBSession.add(Extraction(name=name)) flash('New Extraction successfully created', 'ok') return redirect('./index') @expose() @require(predicates.in_any_group('manager', 'admin')) def delete(self, uid): extraction = DBSession.query(Extraction).get(uid) or abort(404) DBSession.delete(extraction) flash('Extraction correctly deleted') return redirect(tg.url('/extractions')) @expose('etl.templates.extractions.view') @expose(content_type="text/csv") @expose(content_type='application/json') @require(predicates.Any(predicates.not_anonymous(), is_api_authenticated())) @validate( { 'extraction': Convert( lambda v: DBSession.query(Extraction).filter_by(uid=v).one()) }, error_handler=abort(404, error_handler=True)) def view(self, extraction, extraction_filter=None, **kw): try: result = extraction.perform() except Exception as e: log.exception('Failed to Retrieve Data') flash('ERROR RETRIEVING DATA: %s' % e, 'error') return redirect('/error') e_filter = None try: if extraction_filter: if int(extraction_filter ) != -1: # -1 = original extraction requested by user e_filter = DBSession.query(ExtractionFilter).get( extraction_filter) if not e_filter: return abort(404) result = e_filter.perform(result) else: default = DBSession.query(ExtractionFilter).filter( ExtractionFilter.default == True, ExtractionFilter.extraction_id == extraction.uid).first() if default: e_filter = default result = default.perform(result) except Exception as e: log.exception('Failed to Retrieve Data') flash('ERROR RETRIEVING DATA: %s' % e, 'error') result = DataFrame() if request.response_type == 'text/csv': return dateframe_to_csv(result) elif request.response_type == 'application/json': return dateframe_to_json(result) visualizations = dict( (name, None) for name in extraction.visualization.split('+')) axis = [] if extraction.graph_axis: axis = [x.strip() for x in extraction.graph_axis.split(',')] visualizations = get_graph(result, axis, visualizations) if config.get("extraction.max_elements") is None: log.warn( "Cannot find max elements to render in config file. Using default 10000" ) if len(result) * len(result.columns) > int( config.get("extraction.max_elements", 10000)): flash( "There are too many data to extract, please add some filters", "error") filters = DBSession.query(ExtractionFilter).filter_by( extraction_id=extraction.uid).all() return dict(extraction=extraction, visualizations=visualizations, columns=result.columns, results=result.itertuples(), count=len(result), filters=filters, extraction_filter=e_filter, py2=py_version < 3) @expose() def reload_data(self, extraction): extraction = DBSession.query(Extraction).get(extraction) or abort(404) for dts in extraction.datasets: empty_cache(dts.dataset.cache_key()) empty_cache(dts.dataset.cache_key(DEFAULT_LIMIT_FOR_PERFORMANCE)) flash('Data reloaded') return redirect('/extractions/view/' + str(extraction.uid))
def fetch(self, page, rows, sidx='mb', sord='asc', _search='false', searchOper=None, searchField=None, searchString=None, **kw): ''' Function called on AJAX request made by FlexGrid Fetch data ''' log.debug('fetch') # Try and use grid preference grid_rows = session.get('grid_rows') if rows=='-1': # Default value rows = grid_rows if grid_rows is not None else 25 # Save grid preference session['grid_rows'] = rows session.save() rows = int(rows) log.debug('rows=%d' % rows) try: page = int(page) rows = int(rows) offset = (page-1) * rows except: offset = 0 page = 1 rows = 25 q = DBSession.query(Phone) if in_group('CDS'): dptm = [p.department.dptm_id for p in request.identity['user'].phone] q = q.filter(Phone.department_id.in_(dptm)) elif not in_group('admin'): u = DBSession.query(User).get(request.identity['user'].user_id) q = q.filter(Phone.user_id==u.user_id) sip2ext = dict([(p.sip_id, p.exten) for p in q]) cfs = [] man = Globals.manager.command('database show CFIM') for i,r in enumerate(man.response[3:-2]): match = re_db.search(r) if match: k, v = match.groups() if k in sip2ext.keys(): cfs.append((sip2ext[k], 'CFIM', v)) man = Globals.manager.command('database show CFBS') for i,r in enumerate(man.response[3:-2]): match = re_db.search(r) if match: k, v = match.groups() if k in sip2ext.keys(): cfs.append((sip2ext[k], 'CFBS', v)) man = Globals.manager.command('database show CFUN') for i,r in enumerate(man.response[3:-2]): match = re_db.search(r) if match: k, v = match.groups() if k in sip2ext.keys(): cfs.append((sip2ext[k], 'CFUN', v)) man = Globals.manager.command('database show CFVM') for i,r in enumerate(man.response[3:-2]): match = re_db.search(r) if match: k, v = match.groups() if k in sip2ext.keys(): cfs.append((sip2ext[k], 'CFVM', v)) log.debug('Call forwards-> %s' % (cfs)) # sort_key = lambda x : x[sidx] data = [] total = 0 for i, c in enumerate(cfs): data.append({'id' : i, 'cell': row(c)}) total += 1 return dict(page=page, total=total, rows=data)
class AdminController(TGController): """ A basic controller that handles User Groups and Permissions for a TG application. """ allow_only = in_group('managers') def __init__(self, models, session, config_type=None, translations=None): super(AdminController, self).__init__() if translations is None: translations = {} if config_type is None: config = AdminConfig(models, translations) else: config = config_type(models, translations) if config.allow_only: self.allow_only = config.allow_only self.config = config self.session = session self.missing_template = False if self.config.default_index_template: expose(self.config.default_index_template)(self.index) else: if milestones is None: self._choose_index_template() else: milestones.renderers_ready.register( self._choose_index_template) self.controllers_cache = {} def _choose_index_template(self): default_renderer = getattr(tg_config, 'default_renderer', 'genshi') if default_renderer not in ['genshi', 'mako', 'jinja']: if 'genshi' in tg_config.renderers: default_renderer = 'genshi' elif 'mako' in tg_config.renderers: default_renderer = 'mako' elif 'jinja' in tg_config.renderers: default_renderer = 'jinja' else: log.warn( 'TurboGears admin supports only Genshi, Mako and Jinja, please make sure you add at \ least one of those to your config/app_cfg.py base_config.renderers list.') self.missing_template = True index_template = ':'.join( (default_renderer, self.config.layout.template_index)) expose(index_template)(self.index) @with_trailing_slash @expose() def index(self): if self.missing_template: raise Exception( 'TurboGears admin supports only Genshi, Mako and Jinja, please make sure you add at \ least one of those to your config/app_cfg.py base_config.renderers list.') return dict( models=[model.__name__ for model in self.config.models.values()]) def _make_controller(self, config, session): m = config.model Controller = config.defaultCrudRestController class ModelController(Controller): model = m table = config.table_type(session) table_filler = config.table_filler_type(session) new_form = config.new_form_type(session) new_filler = config.new_filler_type(session) edit_form = config.edit_form_type(session) edit_filler = config.edit_filler_type(session) allow_only = config.allow_only if hasattr(config.layout, 'crud_resources'): resources = config.layout.crud_resources def _before(self, *args, **kw): super(self.__class__, self)._before(*args, **kw) tmpl_context.make_pager_args = make_pager_args if request.response_type not in ('application/json', ): default_renderer = getattr(tg_config, 'default_renderer', 'genshi') for layout_template in ('get_all', 'new', 'edit'): for template in config.layout.crud_templates.get( layout_template, []): if template.startswith(default_renderer): override_template( getattr(self, layout_template), template) menu_items = None if self.config.include_left_menu: menu_items = self.config.models return ModelController(session, menu_items) @expose() def _lookup(self, model_name, *args): model_name = model_name[:-1] try: model = self.config.models[model_name] except KeyError: raise HTTPNotFound() try: controller = self.controllers_cache[model_name] except KeyError: config = self.config.lookup_controller_config(model_name) controller = self.controllers_cache[ model_name] = self._make_controller(config, self.session) return controller, args @expose() def lookup(self, model_name, *args): return self._lookup(model_name, *args)
def put(self, **kw): ''' Update user in DB ''' if not in_group('admin') and request.identity['user'].user_id != kw['user_id']: flash(u'Accès interdit !', 'error') redirect('/') uid = int(kw['user_id']) log.info('update user %d (voicemail=%s, email_voicemail=%s)' % (uid, kw['voicemail'], kw['email_voicemail'])) u = DBSession.query(User).get(uid) u.firstname = kw['firstname'] u.lastname = kw['lastname'] u.email_address = kw['email_address'] u.fax = kw['fax'] u.voicemail = kw['voicemail'] u.email_voicemail = kw['email_voicemail'] u.password = kw['pwd1'] u.display_name = u.lastname + ' ' + u.firstname u.ascii_name = asterisk_string(u.display_name) for p in u.phone: # Update fax_reject if u.fax: Globals.manager.send_action({'Action': 'DBdel', 'Family': 'fax_reject', 'Key': p.exten}) else: Globals.manager.send_action({'Action': 'DBput', 'Family': 'fax_reject', 'Key': p.exten, 'Val': 1}) # Update voicemail # First, delete existing voicemail entry Globals.manager.update_config( dir_ast + 'voicemail.conf', None, [('Delete', 'astportal', p.exten)]) rmtree('%s/%s' % (dir_vm, p.exten), True) log.info('Delete voicemail directory %s/%s' % (dir_vm, p.exten)) res = Globals.manager.update_config( sip_file, sip_chan, [('Delete', p.sip_id, mailbox)]) log.debug('Update SIP (delete mb) returns %s' % res) if u.voicemail: # Then, add new voicemail vm = u'>%s,%s,%s' \ % (u.password, u.ascii_name, u.email_address if u.email_voicemail else '') res = Globals.manager.update_config( dir_ast + 'voicemail.conf', 'app_voicemail', [('Append', 'astportal', p.exten, vm)]) log.debug('Update voicemail.conf returns %s' % res) res = Globals.manager.update_config( sip_file, sip_chan, [('Append', p.sip_id, mailbox, '%s@astportal' % p.exten)] ) log.debug('Update SIP (append) returns %s' % res) # Last, reload Asterisk Globals.manager.send_action({'Action': 'Command', 'command': 'voicemail reload'}) Globals.manager.send_action({'Action': 'Command', 'command': sip_type + ' reload' }) if kw.has_key('user_name'): # Modification par administrateur u.user_name = kw['user_name'] u.groups = DBSession.query(Group). \ filter(Group.group_id.in_(kw['groups'])).all() flash(u'Utilisateur modifié') redirect('/users/%d/edit' % uid)
class AdminController(TGController): """ A basic controller that handles User Groups and Permissions for a TG application. """ allow_only = in_group('managers') def __init__(self, models, session, config_type=None, translations=None): super(AdminController, self).__init__() if translations is None: translations = {} if config_type is None: config = AdminConfig(models, translations) else: config = config_type(models, translations) if config.allow_only is not None: self.allow_only = config.allow_only self.config = config self.session = session self.missing_template = False if self.config.default_index_template: expose(self.config.default_index_template)(self.index) else: if milestones is None: self._choose_index_template() else: milestones.renderers_ready.register( self._choose_index_template) self.controllers_cache = {} @classmethod def _get_default_renderer(cls): default_renderer = getattr(tg_config, 'default_renderer', 'genshi') if default_renderer not in ['genshi', 'mako', 'jinja', 'kajiki']: if 'genshi' in tg_config.renderers: default_renderer = 'genshi' elif 'kajiki' in tg_config.renderers: default_renderer = 'kajiki' elif 'mako' in tg_config.renderers: default_renderer = 'mako' elif 'jinja' in tg_config.renderers: default_renderer = 'jinja' else: default_renderer = None log.warn( 'TurboGears admin supports only Genshi, Kajiki, Mako and Jinja.' ' please make sure you add at least one of those to your config/app_cfg.py' ' base_config.renderers list.') return default_renderer def _choose_index_template(self): default_renderer = self._get_default_renderer() if not default_renderer: self.missing_template = True return index_template = ':'.join( (default_renderer, self.config.layout.template_index)) expose(index_template)(self.index) @with_trailing_slash @expose() def index(self): if self.missing_template: raise Exception( 'TurboGears admin supports only Genshi, Kajiki, Mako and Jinja.' ' please make sure you add at least one of those to your config/app_cfg.py' ' base_config.renderers list.') return dict( config=self.config, payoff=self.config.index_payoff, project_name=self.config.project_name or tg_config['package_name'].capitalize(), model_config=lambda model: (model.lower(), getattr(self.config, model.lower(), self.config. DefaultControllerConfig)), models=[model.__name__ for model in self.config.models.values()]) @classmethod def make_controller(cls, config, session, left_menu_items=None): """New CRUD controllers using the admin configuration can be created using this.""" m = config.model Controller = config.defaultCrudRestController class ModelController(Controller): model = m table = config.table_type(session) table_filler = config.table_filler_type(session) new_form = config.new_form_type(session) new_filler = config.new_filler_type(session) edit_form = config.edit_form_type(session) edit_filler = config.edit_filler_type(session) allow_only = config.allow_only if hasattr(config.layout, 'crud_resources'): resources = config.layout.crud_resources def _before(self, *args, **kw): super(self.__class__, self)._before(*args, **kw) tmpl_context.make_pager_args = make_pager_args if request.response_type not in ('application/json', ): default_renderer = AdminController._get_default_renderer() for action in ('get_all', 'new', 'edit'): for template in config.layout.crud_templates.get( action, []): if template.startswith(default_renderer): override_template(getattr(self, action), template) return ModelController(session, left_menu_items) @expose() def _lookup(self, model_name, *args): model_name = model_name[:-1] try: model = self.config.models[model_name] except KeyError: raise HTTPNotFound() try: controller = self.controllers_cache[model_name] except KeyError: config = self.config.lookup_controller_config(model_name) menu_items = None if self.config.include_left_menu: menu_items = self.config.models controller = self.controllers_cache[ model_name] = self.make_controller(config, self.session, left_menu_items=menu_items) return controller, args @expose() def lookup(self, model_name, *args): return self._lookup(model_name, *args)
class DashboardController(BaseController): @expose('etl.templates.dashboard.index') @require(predicates.not_anonymous()) def index(self, id=None): try: if not id: dashboard = DBSession.query(Dashboard).first() else: dashboard = DBSession.query(Dashboard).filter_by(uid=id).one() if not dashboard: raise NoResultFound() except NoResultFound: return abort(404, detail='dashboard not found') sorted_extractions = dashboard.extractions sorted_extractions.sort(key=lambda e: e.index) columned_extractions = gridify(sorted_extractions, getter=lambda e: e.columns) return dict(dashboard=dashboard, columned_extractions=columned_extractions) @expose('etl.templates.dashboard.edit') @require(predicates.in_group('admin')) def new(self): dashboard = Dashboard() dashboard.name = 'New dashboard' DBSession.add(dashboard) all_extractions = DBSession.query(Extraction).all() return dict( dashboard=dashboard, form_dashboard_name=DashboardChangeName(), form_dashboard_name_values=dashboard, visualizationtypes=visualizationtypes, all_extractions=all_extractions, ) @expose('etl.templates.dashboard.edit') @require(predicates.in_group('admin')) def edit(self, id=None): try: dashboard = DBSession.query(Dashboard).filter_by(uid=id).one() except NoResultFound: return abort(404, detail='dashboard not found') all_extractions = DBSession.query(Extraction).all() return dict( dashboard=dashboard, form_dashboard_name=DashboardChangeName(), form_dashboard_name_values=dashboard, visualizationtypes=visualizationtypes, all_extractions=all_extractions, ) @expose() @require(predicates.in_group('admin')) def delete(self, dashboard_id): if dashboard_id == '1': return abort(400, detail='cannot delete the main dashboard') dashboard = DBSession.query(Dashboard).filter_by( uid=dashboard_id).one() DBSession.delete(dashboard) return redirect('/dashboard') @expose() @require(predicates.in_group('admin')) @validate(DashboardChangeName, error_handler=edit) def save_name(self, **kw): try: dashboard = DBSession.query(Dashboard).filter_by( uid=kw['uid']).one() except NoResultFound: return abort(404, detail='dashboard not found') dashboard.name = kw['name'] return redirect('/dashboard/edit/%s' % kw['uid']) @expose('json') @require(predicates.in_group('admin')) def save_extraction(self, dashboard_id, **kw): axis = request.json['graph_axis'] visualization_type = request.json['visualization'] validate_axis_against_extraction_visualization( visualization_type, axis, DBSession.query(Extraction).get(int( request.json['extraction_id']))) try: de = DBSession.query(DashboardExtractionAssociation).filter( DashboardExtractionAssociation.uid == request.json['uid'], ).one() except (NoResultFound, KeyError): de = DashboardExtractionAssociation() de.dashboard_id = int(dashboard_id) de.extraction_id = request.json['extraction_id'] de.extraction_id = request.json['extraction_id'] de.visualization = visualization_type de.graph_axis = axis de.index = request.json['index'] try: columns = int(request.json['columns']) except ValueError: abort(412, detail='columns must be an integer beetween 4 and 8') if 8 < columns or 4 > columns: abort(412, detail='columns must be between 4 and 8') de.columns = columns DBSession.add(de) return dict( de=de, dashboard=de.dashboard, extraction=de.extraction, ) @expose('json') @require(predicates.in_group('admin')) def delete_extraction(self, dashboard_id): uid = request.json['uid'] try: de = DBSession.query(DashboardExtractionAssociation).filter( DashboardExtractionAssociation.uid == uid, ).one() DBSession.delete(de) except NoResultFound: pass return dict() @expose('json') @require(predicates.in_group('admin')) def set_extraction_index(self, dashboard_id): uid = request.json['uid'] new_index = request.json['index'] if new_index < 0: return abort(400, detail='cannot raise first extraction') last_index = DBSession.query(func.max(DashboardExtractionAssociation.index))\ .filter_by(dashboard_id=dashboard_id).one()[0] if new_index > last_index: return abort(400, detail='cannot lower last extraction') try: de = DBSession.query(DashboardExtractionAssociation).filter( DashboardExtractionAssociation.uid == uid, ).one() except NoResultFound: return abort(404, detail='dashboard not found') old_index = de.index try: other_de = DBSession.query(DashboardExtractionAssociation).filter( DashboardExtractionAssociation.dashboard_id == dashboard_id, DashboardExtractionAssociation.index == new_index, ).one() other_de.index = old_index except NoResultFound: other_de = None de.index = new_index return dict(de=de, other_de=other_de) @expose('json') @require(predicates.in_group('admin')) def extractions(self, dashboard_id, **kw): try: dashboard = DBSession.query(Dashboard).filter_by( uid=dashboard_id).one() except NoResultFound: return abort(404, detail='dashboard not found') extractions = [de.extraction for de in dashboard.extractions] return dict(extractions=extractions, dashboard=dashboard) @expose('json') @require(predicates.in_group('admin')) def get_extraction(self, uid): try: extraction = DBSession.query(Extraction).filter_by(uid=uid).one() except NoResultFound: return abort(404, detail='extraction not found') return dict(extraction=extraction) @expose('etl.templates.dashboard.extraction_widget') @require(predicates.not_anonymous()) def extraction_widget(self, dashboard_id, **kw): de = DBSession.query(DashboardExtractionAssociation).filter_by( uid=kw['uid']).one() extraction = de.extraction try: result = extraction.perform() except Exception as e: log.exception('Failed to Retrieve Data') flash('ERROR RETRIEVING DATA: %s' % e, 'error') return redirect('/error') visualization = None axis = [] if de.graph_axis: axis = [x.strip() for x in de.graph_axis.split(',')] if 'histogram' == de.visualization: x = result[axis[0]].values y = result[axis[1]].values legend = 0 try: visualization = figure(x_range=x, sizing_mode='scale_width', height=400) visualization.vbar(x=x, top=y, width=0.75, color='#77d6d5') visualization.y_range.start = 0 visualization.y_range.end = max(y if y.size > 0 else [0]) visualization.xaxis.major_label_orientation = "vertical" visualization.toolbar_location = None except Exception as e: # return abort(400, detail=str(e)) return redirect('/error', params={'detail': str(e)}) elif 'line' == de.visualization: if not isinstance(result.index, LINECHART_SUPPORTED_INDEXES): return dict( error= 'LineChart graph is only supported for scalar indexes, currently {}' .format(type(result.index))) x = result[axis[0]].values try: visualization = figure(x_range=x, sizing_mode='scale_width', height=400) except: visualization = figure(sizing_mode='scale_width', height=400) if result[axis[0]].dtype.type == np.datetime64: from datetime import datetime x = [ datetime(year=date.year, month=date.month, day=date.day) for date in pandas.to_datetime(result[axis[0]].values) ] visualization = figure(sizing_mode='scale_width', height=400, x_axis_type='datetime') for i, c in zip(range(1, len(axis)), color_gen()): y = [ j.encode('utf8') if isinstance(j, unicode) else j for j in result[axis[i]].values.tolist() ] try: visualization = figure(y_range=y, sizing_mode='scale_width', height=400) except: pass visualization.line(x, y, color=c) visualization.circle(x, y, color=c, size=3) visualization.toolbar_location = None visualization.yaxis.axis_line_width = None visualization.xgrid.grid_line_color = None visualization.outline_line_color = None visualization.xaxis.axis_line_color = "#777777" visualization.axis.minor_tick_in = 0 visualization.axis.minor_tick_out = 0 visualization.axis.major_tick_in = 0 elif 'pie' == de.visualization: visualization = figure(plot_height=400, sizing_mode='scale_width', x_range=(-0.5, 1.0), toolbar_location=None, tools="hover", tooltips="@%s: @%s" % (axis[0], axis[1])) result = pie_result(result, axis) visualization.wedge(x=0, y=1, radius=0.4, start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'), line_alpha=0, fill_color='color', legend=axis[0], source=result) visualization.axis.axis_label = None visualization.axis.visible = False visualization.grid.grid_line_color = None visualization.toolbar_location = None visualization.outline_line_color = None visualization.legend.border_line_alpha = 0 visualization.legend.location = "center_right" visualization.legend.label_text_font_size = '9pt' visualization.legend.glyph_height = 18 visualization.legend.glyph_width = 18 elif 'sum' == de.visualization: try: visualization = result[axis[0]].sum() except TypeError as ex: visualization = 'Error: ' + str(ex) elif 'average' == de.visualization: try: visualization = result[axis[0]].sum() / len(result[axis[0]]) except Exception as ex: log.exception(str(ex)) visualization = 'Error: ' + str(ex) else: return redirect( '/error', params={'detail': '%s not supported' % de.visualization}) return dict(extraction=extraction, visualization=visualization, visualization_type=de.visualization, axis=axis, columns=result.columns, results=result.itertuples(), count=len(result))
def validate(self, params, state): log.debug(params) f = admin_edit_user_form if in_group('admin') else edit_user_form return f.validate(params, state)
class MolepawAdminConfig(TGAdminConfig): allow_only = predicates.in_group('admin')
def manager_permission(): from tg.predicates import in_group, has_permission, Any return Any(in_group('tgcmanager'), has_permission('tgcomments-manage'))
class FortressAdminConfig(TGAdminConfig): allow_only = predicates.in_group('administrators')
def test_user_belongs_to_group(self): environ = make_environ('gustavo', ['developers']) p = predicates.in_group('developers') self.eval_met_predicate(p, environ)
def fetch(self, page, rows, sidx='user_name', sord='asc', _search='false', searchOper=None, searchField=None, searchString=None, **kw): # Try and use grid preference grid_rows = session.get('grid_rows', None) if rows=='-1': # Default value rows = grid_rows if grid_rows is not None else 25 # Save grid preference session['grid_rows'] = rows session.save() rows = int(rows) try: page = int(page) rows = int(rows) offset = (page-1) * rows except: offset = 0 page = 1 rows = 25 users = {} for u in DBSession.query(User): users[u.user_id] = u.user_name records = DBSession.query(Record, Queue). \ filter(Record.queue_id==Queue.queue_id) filter = [] custom1 = session.get('custom1', None) member = session.get('member', None) queue = session.get('queue', None) date = session.get('date', None) hour = session.get('hour', None) if custom1 is not None: filter.append(u'Client %s' % custom1) records = records.filter(Record.custom1==custom1) if member is not None and member!=-1: filter.append(u'Groupe %s' % member) records = records.filter(Record.member_id==member) if queue is not None and queue!=-1: filter.append(u'Groupe %s' % queue) records = records.filter(Record.queue_id==queue) if date is not None: filter.append(u'date %s' % date.strftime('%d/%m/%Y')) if db_engine=='oracle': records = records.filter(sqlalchemy.func.trunc(CDR.calldate, 'J')==date) else: # PostgreSql records = records.filter(sqlalchemy.sql.cast(Record.created, sqlalchemy.types.DATE) == date) if hour is not None: filter.append(u'heure approximative %dh%02d' % (hour[0], hour[1])) if db_engine=='oracle': if hour[1]>=30: hour1 = '%02d:%02d' % (hour[0], hour[1]-30) hour2 = '%02d:%02d' % (hour[0]+1, hour[1]-30) else: hour1 = '%02d:%02d' % (hour[0]-1, hour[1]+30) hour2 = '%02d:%02d' % (hour[0], hour[1]+30) records = records.filter(hour1<=sqlalchemy.func.to_char(Record.created, 'HH24:MI')) records = records.filter(sqlalchemy.func.to_char(Record.created, 'HH24:MI')<=hour2) else: # PostgreSql hour = '%d:%02d' % (hour[0], hour[1]) records = records.filter("'%s' - '%s'::interval <= record.created::time AND record.created::time <= '%s' + '%s'::interval" % (hour, interval, hour, interval)) # if len(filter): # m = u'Critères: ' if len(filter)>1 else u'Critere: ' # flash( m + ', et '.join(filter) + '.') # Access rights if not in_group('admin'): user_queues = [] for q in DBSession.query(Queue): if in_group('SV ' + q.name): user_queues.append(q.queue_id) log.debug('User queues: %s' % user_queues) records = records.filter(Record.queue_id.in_(user_queues)) total = records.count()/rows + 1 column = getattr(Record, sidx) records = records.order_by(getattr(column,sord)()).offset(offset).limit(rows) rows = [ { 'id' : r.Record.record_id, 'cell': row(r, users) } for r in records ] return dict(page=page, total=total, rows=rows)
class UserRestController(TIMRestController): """ CRUD Controller allowing to manage Users """ allow_only = predicates.in_any_group(Group.TIM_MANAGER_GROUPNAME, Group.TIM_ADMIN_GROUPNAME) password = UserPasswordAdminRestController() profile = UserProfileAdminRestController() workspaces = UserWorkspaceRestController() @classmethod def current_item_id_key_in_context(cls): return 'user_id' @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME)) @tg.expose('tracim.templates.admin.user_getall') def get_all(self, *args, **kw): current_user = tmpl_context.current_user api = UserApi(current_user) users = api.get_all() current_user_content = Context(CTX.CURRENT_USER).toDict(current_user) fake_api = Context(CTX.USERS).toDict( {'current_user': current_user_content}) dictified_users = Context(CTX.USERS).toDict(users, 'users', 'user_nb') return DictLikeClass(result=dictified_users, fake_api=fake_api) @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME)) @tg.expose() def post( self, name: str, email: str, password: str, is_tracim_manager: str = 'off', is_tracim_admin: str = 'off', send_email: str = 'off', ): is_tracim_manager = h.on_off_to_boolean(is_tracim_manager) is_tracim_admin = h.on_off_to_boolean(is_tracim_admin) send_email = h.on_off_to_boolean(send_email) current_user = tmpl_context.current_user if current_user.profile.id < Group.TIM_ADMIN: # A manager can't give large rights is_tracim_manager = False is_tracim_admin = False api = UserApi(current_user) if api.user_with_email_exists(email): tg.flash( _('A user with email address "{}" already exists.').format( email), CST.STATUS_ERROR) tg.redirect(self.url()) user = api.create_user() user.email = email user.display_name = name if password: user.password = password elif send_email: # Setup a random password to send email at user password = str(uuid.uuid4()) user.password = password user.webdav_left_digest_response_hash = '%s:/:%s' % (email, password) api.save(user) # Now add the user to related groups group_api = GroupApi(current_user) user.groups.append(group_api.get_one(Group.TIM_USER)) if is_tracim_manager: user.groups.append(group_api.get_one(Group.TIM_MANAGER)) if is_tracim_admin: user.groups.append(group_api.get_one(Group.TIM_ADMIN)) api.save(user) if send_email: email_manager = get_email_manager() email_manager.notify_created_account(user, password=password) tg.flash( _('User {} created.').format(user.get_display_name()), CST.STATUS_OK) tg.redirect(self.url()) @tg.expose('tracim.templates.admin.user_getone') def get_one(self, user_id): current_user = tmpl_context.current_user api = UserApi(current_user) # role_api = RoleApi(tg.tmpl_context.current_user) # user_api = UserApi(tg.tmpl_context.current_user) user = api.get_one(user_id) # FIXME role_api = RoleApi(tg.tmpl_context.current_user) role_list = role_api.get_roles_for_select_field() dictified_user = Context(CTX.ADMIN_USER).toDict(user, 'user') current_user_content = Context(CTX.CURRENT_USER).toDict( tmpl_context.current_user) fake_api_content = DictLikeClass(current_user=current_user_content, role_types=role_list) fake_api = Context(CTX.ADMIN_USER).toDict(fake_api_content) return DictLikeClass(result=dictified_user, fake_api=fake_api) @tg.expose('tracim.templates.admin.user_edit') def edit(self, id): current_user = tmpl_context.current_user api = UserApi(current_user) user = api.get_one(id) dictified_user = Context(CTX.USER).toDict(user, 'user') return DictLikeClass(result=dictified_user) @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME)) @tg.expose() def put(self, user_id, name, email, next_url=''): api = UserApi(tmpl_context.current_user) user = api.get_one(int(user_id)) api.update(user, name, email, True) tg.flash( _('User {} updated.').format(user.get_display_name()), CST.STATUS_OK) if next_url: tg.redirect(next_url) tg.redirect(self.url()) @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME)) @tg.expose() def enable(self, id, next_url=None): current_user = tmpl_context.current_user api = UserApi(current_user) user = api.get_one(id) user.is_active = True api.save(user) tg.flash( _('User {} enabled.').format(user.get_display_name()), CST.STATUS_OK) if next_url == 'user': tg.redirect(self.url(id=user.user_id)) tg.redirect(self.url()) @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME)) @tg.expose() def disable(self, id, next_url=None): id = int(id) current_user = tmpl_context.current_user api = UserApi(current_user) if current_user.user_id == id: tg.flash(_('You can\'t de-activate your own account'), CST.STATUS_ERROR) else: user = api.get_one(id) user.is_active = False api.save(user) tg.flash( _('User {} disabled').format(user.get_display_name()), CST.STATUS_OK) if next_url == 'user': tg.redirect(self.url(id=user.user_id)) tg.redirect(self.url()) @tg.require(predicates.in_group(Group.TIM_USER_GROUPNAME)) @tg.expose('tracim.templates.user_profile') def me(self): current_user = tmpl_context.current_user current_user_content = Context(CTX.CURRENT_USER).toDict(current_user) fake_api = Context(CTX.ADMIN_WORKSPACE).toDict( {'current_user': current_user_content}) return DictLikeClass(fake_api=fake_api)
def test_user_doesnt_belong_to_group(self): environ = make_environ('gustavo', ['developers', 'admins']) p = predicates.in_group('designers') self.eval_unmet_predicate(p, environ, 'The current user must belong to the group "designers"')
class UserProfileAdminRestController(TIMRestController): """CRUD Controller allowing to manage groups of a user.""" allow_only = predicates.in_group(Group.TIM_ADMIN_GROUPNAME) _ALLOWED_PROFILE_USER = '******' _ALLOWED_PROFILE_MANAGER = 'tracim-profile-manager' _ALLOWED_PROFILE_ADMIN = 'tracim-profile-admin' @property def allowed_profiles(self): return [ UserProfileAdminRestController._ALLOWED_PROFILE_USER, UserProfileAdminRestController._ALLOWED_PROFILE_MANAGER, UserProfileAdminRestController._ALLOWED_PROFILE_ADMIN, ] def _before(self, *args, **kw): """ Instantiate the current workspace in tg.tmpl_context. :param args: :param kw: :return: """ super(self.__class__, self)._before(args, kw) api = UserApi(tg.tmpl_context.current_user) user_id = tg.request.controller_state.routing_args.get('user_id') user = api.get_one(user_id) tg.tmpl_context.user_id = user_id tg.tmpl_context.user = user @tg.expose() def switch(self, new_role) -> None: """ Switch to the given new role. :param new_role: value should be: 'tracim-user', 'tracim-manager' (allowed to create workspaces) or 'tracim-admin' (admin the whole system) """ return self.put(new_role) @tg.expose() def put(self, new_profile): # FIXME - Allow only self password or operation for managers current_user = tmpl_context.current_user user = tmpl_context.user group_api = GroupApi(current_user) if current_user.user_id == user.user_id: tg.flash(_('You can\'t change your own profile'), CST.STATUS_ERROR) tg.redirect(self.parent_controller.url()) redirect_url = self.parent_controller.url(skip_id=True) if new_profile not in self.allowed_profiles: tg.flash(_('Unknown profile'), CST.STATUS_ERROR) tg.redirect(redirect_url) pod_user_group = group_api.get_one(Group.TIM_USER) pod_manager_group = group_api.get_one(Group.TIM_MANAGER) pod_admin_group = group_api.get_one(Group.TIM_ADMIN) # this is the default value ; should never appear flash_message = _('User updated.') if new_profile == UserProfileAdminRestController._ALLOWED_PROFILE_USER: if pod_user_group not in user.groups: user.groups.append(pod_user_group) try: user.groups.remove(pod_manager_group) except: pass try: user.groups.remove(pod_admin_group) except: pass flash_message = _('User {} is now a basic user').format(user.get_display_name()) elif new_profile == UserProfileAdminRestController._ALLOWED_PROFILE_MANAGER: if pod_user_group not in user.groups: user.groups.append(pod_user_group) if pod_manager_group not in user.groups: user.groups.append(pod_manager_group) try: user.groups.remove(pod_admin_group) except: pass flash_message = _('User {} can now workspaces').format(user.get_display_name()) elif new_profile == UserProfileAdminRestController._ALLOWED_PROFILE_ADMIN: if pod_user_group not in user.groups: user.groups.append(pod_user_group) if pod_manager_group not in user.groups: user.groups.append(pod_manager_group) if pod_admin_group not in user.groups: user.groups.append(pod_admin_group) flash_message = _('User {} is now an administrator').format(user.get_display_name()) else: error_msg = \ 'Trying to change user {} profile with unexpected profile {}' logger.error(self, error_msg.format(user.user_id, new_profile)) tg.flash(_('Unknown profile'), CST.STATUS_ERROR) tg.redirect(redirect_url) DBSession.flush() tg.flash(flash_message, CST.STATUS_OK) tg.redirect(redirect_url) def get_edit(self): pass def get_all(self): pass def post(self): pass
class UserRestController(TIMRestController): """CRUD Controller allowing to manage Users.""" allow_only = predicates.in_any_group( Group.TIM_MANAGER_GROUPNAME, Group.TIM_ADMIN_GROUPNAME, ) password = UserPasswordAdminRestController() profile = UserProfileAdminRestController() workspaces = UserWorkspaceRestController() PASSWORD_LENGTH = 12 PASSWORD_CHARACTERS = '0123456789' \ 'abcdefghijklmonpqrstuvwxyz' \ 'ABCDEFGHIJKLMONPQRSTUVWXYZ' @classmethod def current_item_id_key_in_context(cls): return 'user_id' @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME)) @tg.expose('tracim.templates.admin.user_getall') def get_all(self, *args, **kw): current_user = tmpl_context.current_user api = UserApi(current_user) users = api.get_all() current_user_content = Context(CTX.CURRENT_USER).toDict(current_user) fake_api = Context(CTX.USERS).toDict({'current_user': current_user_content}) dictified_users = Context(CTX.USERS).toDict(users, 'users', 'user_nb') return DictLikeClass(result=dictified_users, fake_api=fake_api) @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME)) @tg.expose() def post( self, name: str, email: str, password: str, is_tracim_manager: str='off', is_tracim_admin: str='off', send_email: str='off', ): is_tracim_manager = h.on_off_to_boolean(is_tracim_manager) is_tracim_admin = h.on_off_to_boolean(is_tracim_admin) send_email = h.on_off_to_boolean(send_email) current_user = tmpl_context.current_user if current_user.profile.id < Group.TIM_ADMIN: # A manager can't give large rights is_tracim_manager = False is_tracim_admin = False api = UserApi(current_user) if api.user_with_email_exists(email): tg.flash(_('A user with email address "{}" already exists.').format(email), CST.STATUS_ERROR) tg.redirect(self.url()) user = api.create_user() user.email = email user.display_name = name if password: user.password = password elif send_email: # Setup a random password to send email at user password = self.generate_password() user.password = password api.save(user) # Now add the user to related groups group_api = GroupApi(current_user) user.groups.append(group_api.get_one(Group.TIM_USER)) if is_tracim_manager: user.groups.append(group_api.get_one(Group.TIM_MANAGER)) if is_tracim_admin: user.groups.append(group_api.get_one(Group.TIM_ADMIN)) api.save(user) email_sent = True if send_email: email_manager = get_email_manager() try: email_manager.notify_created_account(user, password=password) except Exception: email_sent = False api.execute_created_user_actions(user) if not email_sent: tg.flash(_('User {0} created but email was not sent to {1}').format(user.get_display_name(), user.email), CST.STATUS_WARNING) else: tg.flash(_('User {} created.').format(user.get_display_name()), CST.STATUS_OK) tg.redirect(self.url()) @classmethod def generate_password( cls, password_length=PASSWORD_LENGTH, password_chars=PASSWORD_CHARACTERS, ): # character list that will be contained into the password char_list = [] for _unused in range(password_length): # This puts a random char from the list above inside # the list of chars and then merges them into a String char_list.append(random.choice(password_chars)) password = ''.join(char_list) return password @tg.expose('tracim.templates.admin.user_getone') def get_one(self, user_id): current_user = tmpl_context.current_user api = UserApi(current_user) # role_api = RoleApi(tg.tmpl_context.current_user) # user_api = UserApi(tg.tmpl_context.current_user) user = api.get_one(user_id) # FIXME role_api = RoleApi(tg.tmpl_context.current_user) role_list = role_api.get_roles_for_select_field() dictified_user = Context(CTX.ADMIN_USER).toDict(user, 'user') current_user_content = Context(CTX.CURRENT_USER).toDict(tmpl_context.current_user) fake_api_content = DictLikeClass(current_user=current_user_content, role_types=role_list) fake_api = Context(CTX.ADMIN_USER).toDict(fake_api_content) return DictLikeClass(result=dictified_user, fake_api=fake_api) @tg.expose('tracim.templates.admin.user_edit') def edit(self, id): current_user = tmpl_context.current_user api = UserApi(current_user) user = api.get_one(id) dictified_user = Context(CTX.USER).toDict(user, 'user') return DictLikeClass( result=dictified_user, timezones=pytz.all_timezones, ) @tg.require(predicates.in_group(Group.TIM_MANAGER_GROUPNAME)) @tg.expose() def put(self, user_id, name, email, timezone: str='', next_url=''): api = UserApi(tmpl_context.current_user) user = api.get_one(int(user_id)) api.update(user, name, email, True, timezone=timezone) tg.flash(_('User {} updated.').format(user.get_display_name()), CST.STATUS_OK) if next_url: tg.redirect(next_url) tg.redirect(self.url()) @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME)) @tg.expose() def enable(self, id, next_url=None): current_user = tmpl_context.current_user api = UserApi(current_user) user = api.get_one(id) user.is_active = True api.save(user) tg.flash(_('User {} enabled.').format(user.get_display_name()), CST.STATUS_OK) if next_url == 'user': tg.redirect(self.url(id=user.user_id)) tg.redirect(self.url()) @tg.require(predicates.in_group(Group.TIM_ADMIN_GROUPNAME)) @tg.expose() def disable(self, id, next_url=None): id = int(id) current_user = tmpl_context.current_user api = UserApi(current_user) if current_user.user_id == id: tg.flash(_('You can\'t de-activate your own account'), CST.STATUS_ERROR) else: user = api.get_one(id) user.is_active = False api.save(user) tg.flash(_('User {} disabled').format(user.get_display_name()), CST.STATUS_OK) if next_url == 'user': tg.redirect(self.url(id=user.user_id)) tg.redirect(self.url())
def manager_permission(): return in_group('tgcmanager') or has_permission('tgcmanager')
class EventController(TGController): @expose('calendarevents.templates.event.event') @validate(dict(event=SQLAEntityConverter(model.CalendarEvent)), error_handler=fail_with(404)) def _default(self, event): if event.event_type and getattr(event.event_type, 'force_redirect', False): linked_entity_url = event.linked_entity_url if linked_entity_url: return redirect(linked_entity_url) return dict(event=event) @expose('calendarevents.templates.event.new') @require(predicates.in_group('calendarevents')) @validate(dict(cal=SQLAEntityConverter(model.Calendar)), error_handler=fail_with(403)) def new(self, cal, **kw): return dict(cal=cal, form=get_form(), linkable_entities=cal.linkable_entities) @expose() @require(predicates.in_group('calendarevents')) @validate(get_form(), error_handler=validated_handler(new)) def create(self, cal, **kw): new_event = utils.create_event( cal, name=kw['name'], summary=kw['summary'], datetime=kw['datetime'], location=kw['location'], linked_entity_type=cal.events_type, linked_entity_id=kw.get('linked_entity')) flash(_('Event successfully added')) return plug_redirect('calendarevents', '/calendar/%d' % cal.uid) @expose() @require(predicates.in_group('calendarevents')) @validate(dict(event=SQLAEntityConverter(model.CalendarEvent)), error_handler=fail_with(404)) def remove(self, event): referer = request.referer if referer and referer.endswith( plug_url('calendarevents', '/event/%s' % event.uid)): referer = plug_url('calendarevents', '/calendar/%s' % event.calendar_id) DBSession.delete(event) return redirect(referer) @expose('calendarevents.templates.event.edit') @require(predicates.in_group('calendarevents')) @validate(dict(event=SQLAEntityConverter(model.CalendarEvent)), error_handler=fail_with(404)) def edit(self, event, **kw): cal = event.calendar return dict(cal=cal, event=event, linkable_entities=cal.linkable_entities, form=get_form()) @expose() @require(predicates.in_group('calendarevents')) @validate(get_form(), error_handler=validated_handler(edit)) def save(self, event, **kw): event = utils.get_event(event) if not event: abort(404) event.name = kw['name'] event.summary = kw['summary'] event.datetime = kw['datetime'] event.location = kw['location'] event.linked_entity_id = kw.get('linked_entity') flash(_('Event successfully modified')) return plug_redirect('calendarevents', '/event/%s' % event.uid)
class MyAdminController(BaseController): admin = AdminController(model, DBSession, config_type=TGAdminConfig) allow_only = in_group('managers') tags = TagsController(DBSession) @expose('molgears.templates.myadmin.index') def index(self): """ Main page for admin controller """ # userid = request.identity['repoze.who.userid'] return dict(page='index', pname=None) @expose('molgears.templates.myadmin.users') def users(self, page=1, *args, **kw): """ Users Managment. """ users = DBSession.query(User) page_url = paginate.PageURL_WebOb(request) tmpl = '' dsc = True order = 'user_id' if kw: if 'desc' in kw and kw['desc'] != u'': if kw['desc'] != u'1': dsc = False if 'order_by' in kw and kw['order_by'] != u'': order = kw['order_by'] if dsc: users = users.order_by(desc(order).nullslast()) else: users = users.order_by((order)) currentPage = paginate.Page(users, page, url=page_url, items_per_page=30) return dict(page='index', currentPage=currentPage, tmpl=tmpl, pname=None) @require( Any(is_user('manager'), has_permission('manage'), msg='Permission denied')) @expose('molgears.templates.myadmin.new_user') def new_user(self, *args, **kw): """ Add new User. """ try: come_from = request.headers['Referer'] except Exception: come_from = request.path_url groups = DBSession.query(Group).all() if kw: if 'come_from' in kw and kw['come_from'] != u'': come_from = kw['come_from'] if 'password' in kw and kw['password'] != u'': new = kw['password'] if 'verification' in kw and kw[ 'verification'] != u'' and new != kw['verification']: flash(l_(u'Password not match'), 'error') redirect(come_from) else: flash(l_('Verification error'), 'error') else: flash(l_(u'Password is required'), 'error') redirect(come_from) if 'email' in kw and kw['email'] != u'': email = kw['email'] else: flash(l_('Email is required'), 'error') redirect(come_from) if 'items_per_page' in kw and kw['items_per_page'] != u'': try: items_per_page = int(kw['items_per_page']) except Exception: flash(l_('Compounds per page should be a number'), 'error') else: flash(l_('Compounds per page required'), 'error') redirect(come_from) if 'user_name' in kw and kw['user_name'] != u'': user = User() user.user_name = kw['user_name'].strip().replace(' ', '.') else: flash(l_('User name is required'), 'error') redirect(come_from) if 'display_name' in kw and kw['display_name'] != u'': user.display_name = kw['display_name'] if 'groups' in kw and kw['groups'] != u'': if isinstance(kw['groups'], basestring): groups = [DBSession.query(Group).get(kw['groups'])] else: groups = [ DBSession.query(Group).get(group_id) for group_id in kw['groups'] ] else: flash(l_('Group is required'), 'error') redirect(come_from) if items_per_page: if items_per_page > 10 and items_per_page < 150: user.items_per_page = items_per_page else: flash( l_(u'Number of Compound per page should be between 10 and 150' ), 'error') redirect(come_from) if email: import re if len(email) >= 6: if re.match( "^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None: user.email_address = email else: flash(l_(u'Email error'), 'warning') redirect(come_from) else: flash(l_(u'Email error'), 'warning') redirect(come_from) else: flash(l_(u'Email not changed'), 'warning') if new: if len(new) >= 6: user._set_password(new) else: flash(l_(u'Password error'), 'error') redirect(come_from) else: flash(l_('Password is required'), 'error') redirect(come_from) if groups: for group in groups: group.users.append(user) else: flash(l_('Gropus error'), 'error') redirect(come_from) DBSession.add(user) DBSession.flush() flash(l_(u'Task completed successfully')) redirect(come_from) return dict(page='index', come_from=come_from, groups=groups, pname=None) @require( Any(is_user('manager'), has_permission('manage'), msg='Permission denied')) @expose('molgears.templates.myadmin.edit_user') def edit_user(self, *args, **kw): """ Edit User record. """ try: come_from = request.headers['Referer'] except Exception: come_from = request.path_url groups = DBSession.query(Group).order_by('group_id').all() try: user_id = args[0] except Exception: redirect("/error") user = DBSession.query(User).get(user_id) if kw: if 'come_from' in kw and kw['come_from'] != u'': come_from = kw['come_from'] if 'password' in kw and kw['password'] != u'': new = kw['password'] if 'verification' in kw and kw[ 'verification'] != u'' and new != kw['verification']: flash(l_(u'Password not match'), 'error') redirect(come_from) else: new = None if 'email' in kw and kw['email'] != u'': email = kw['email'] else: flash(l_('Email is required'), 'error') redirect(come_from) if 'items_per_page' in kw and kw['items_per_page'] != u'': try: items_per_page = int(kw['items_per_page']) except Exception: flash(l_('Compounds per page should be a number'), 'error') else: flash(l_('Compounds per page required'), 'error') redirect(come_from) if 'user_name' in kw and kw['user_name'] != u'': if kw['user_name'] != user.user_name: user.user_name = kw['user_name'] else: flash(l_('User name is required'), 'error') redirect(come_from) if 'display_name' in kw and kw['display_name'] != u'' and kw[ 'display_name'] != user.display_name: user.display_name = kw['display_name'] if 'groups' in kw and kw['groups'] != u'': if isinstance(kw['groups'], basestring): groups = [DBSession.query(Group).get(kw['groups'])] else: groups = [ DBSession.query(Group).get(group_id) for group_id in kw['groups'] ] else: flash(l_('Group is required'), 'error') redirect(come_from) if items_per_page: if items_per_page > 10 and items_per_page < 150: if user.items_per_page != items_per_page: user.items_per_page = items_per_page else: flash( l_(u'Number of Compound per page should be between 10 and 150' ), 'error') redirect(come_from) if email: import re if len(email) >= 6: if re.match( "^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None: if email != user.email_address: user.email_address = email else: flash(l_(u'Email error'), 'warning') redirect(come_from) else: flash(l_(u'Email error'), 'warning') redirect(come_from) if new: if len(new) >= 6: user._set_password(new) else: flash(l_(u'Password error'), 'error') redirect(come_from) if groups: for group in groups: if user not in group.users: group.users.append(user) for ugroup in user.groups: if ugroup not in groups: ugroup.users.remove(user) else: flash(l_('Gropus error'), 'error') redirect(come_from) DBSession.flush() flash(l_(u'Task completed successfully')) redirect(come_from) return dict(page='index', come_from=come_from, groups=groups, user=user, pname=None) @require( Any(is_user('manager'), has_permission('manage'), msg='Permission denied')) @expose('') def delete_user(self, *args, **kw): try: user_id = args[0] except Exception: redirect("/error") try: come_from = request.headers['Referer'] except Exception: come_from = request.path_url user = DBSession.query(User).get(user_id) if user: for group in user.groups: group.users.remove(user) DBSession.delete(user) else: flash(l_(u'User error'), 'error') redirect(come_from) flash(l_(u'Task completed successfully')) redirect(come_from) @expose('molgears.templates.myadmin.projects') def projects(self, page=1, *args, **kw): """ Projects Managment. """ projects = DBSession.query(Projects) page_url = paginate.PageURL_WebOb(request) tmpl = '' dsc = True order = 'id' if kw: if 'desc' in kw and kw['desc'] != u'': if kw['desc'] != u'1': dsc = False if 'order_by' in kw and kw['order_by'] != u'': order = kw['order_by'] if dsc: projects = projects.order_by(desc(order).nullslast()) else: projects = projects.order_by((order)) currentPage = paginate.Page(projects, page, url=page_url, items_per_page=30) return dict(page='index', currentPage=currentPage, tmpl=tmpl, pname=None) @expose('molgears.templates.myadmin.new_project') @require( Any(is_user('manager'), has_permission('manage'), msg='Permission denied')) def new_project(self, *args, **kw): """ Create new project & group with correct permissions asigned. If you wish to allow users acces to the project- add them to group named as a project. """ userid = request.identity['repoze.who.userid'] user = DBSession.query(User).filter_by(user_name=userid).first() try: come_from = request.headers['Referer'] except Exception: come_from = request.path_url if kw: if 'come_from' in kw and kw['come_from'] != u'': come_from = kw['come_from'] if 'name' in kw and kw['name'] != u'': cell_lines = [] fp_lines = [] htrf_lines = [] for k, v in kw.iteritems(): if 'Cell_Line_' in str(k) and v != u'': cell_lines.append(v.strip().replace(' ', '_')) if 'FP_Line_' in str(k) and v != u'': fp_lines.append(v.strip().replace(' ', '_')) if 'HTRF_Line_' in str(k) and v != u'': htrf_lines.append(v.strip().replace(' ', '_')) if not cell_lines: flash(l_(u'At least 1 Cell_Line is required'), 'error') redirect(come_from) if not fp_lines: flash(l_(u'At least 1 FP_Line is required'), 'error') redirect(come_from) if not htrf_lines: flash(l_(u'At least 1 HTRF_Line is required'), 'error') redirect(come_from) #create new project: project = Projects() project.name = kw['name'].strip().replace(' ', '_') #add group named as a project: gr = Group() gr.group_name = kw['name'].strip().replace(' ', '_') gr.display_name = kw['name'] gr.users.append(user) #add permission named as a project and assign it to group: from molgears.model import Permission perm = Permission() perm.permission_name = kw['name'].strip().replace(' ', '_') perm.groups += [gr] #add description: if 'description' in kw and kw['description'] != u'': project.description = kw['description'] #add test and cell lines ptest = ProjectTests() ptest.name = 'CT' fp_ptest = ProjectTests() fp_ptest.name = 'FP' htrf_ptest = ProjectTests() htrf_ptest.name = 'HTRF' project.tests = [fp_ptest, ptest, htrf_ptest] import pickle if cell_lines: pickle_dump1 = pickle.dumps(cell_lines) ptest.cell_line = pickle_dump1 if fp_lines: pickle_dump2 = pickle.dumps(fp_lines) fp_ptest.cell_line = pickle_dump2 if htrf_lines: pickle_dump3 = pickle.dumps(htrf_lines) htrf_ptest.cell_line = pickle_dump3 DBSession.add(perm) DBSession.add(gr) DBSession.add(ptest) DBSession.add(fp_ptest) DBSession.add(project) DBSession.flush() flash(l_(u'Task completed successfully')) redirect(come_from) else: flash(l_(u'Name is required'), 'error') redirect(come_from) return dict(page='index', userid=userid, come_from=come_from) @expose('molgears.templates.myadmin.edit_project') @require( Any(is_user('manager'), has_permission('manage'), msg='Permission denied')) def edit_project(self, *args, **kw): """ Edit Project. If you wish to allow users acces to the project- add them to group named as a project. """ try: project_id = args[0] except: redirect("error") userid = request.identity['repoze.who.userid'] # user = DBSession.query(User).filter_by(user_name=userid).first() try: come_from = request.headers['Referer'] except Exception: come_from = request.path_url try: project = DBSession.query(Projects).get(project_id) except: flash("Project not exist", "error") redirect(come_from) if kw: if 'come_from' in kw and kw['come_from'] != u'': come_from = kw['come_from'] if 'name' in kw and kw['name'] != u'': fp_lines = [] ct_lines = [] htrf_lines = [] for k, v in kw.iteritems(): if 'FP_Line_' in str(k) and v != u'': fp_lines.append(v) if 'CT_Line_' in str(k) and v != u'': ct_lines.append(v) if 'HTRF_Line_' in str(k) and v != u'': htrf_lines.append(v) if 'CT_Old_Line' in kw and kw['CT_Old_Line'] != u'': if isinstance(kw['CT_Old_Line'], basestring): if kw['CT_Old_Line'] != u'': ct_lines.append(kw['CT_Old_Line']) else: ct_lines += [ cell for cell in kw['CT_Old_Line'] if cell != u'' ] if 'FP_Old_Line' in kw and kw['FP_Old_Line'] != u'': if isinstance(kw['FP_Old_Line'], basestring): if kw['FP_Old_Line'] != u'': fp_lines.append(kw['FP_Old_Line']) else: fp_lines += [ cell for cell in kw['FP_Old_Line'] if cell != u'' ] if 'HTRF_Old_Line' in kw and kw['HTRF_Old_Line'] != u'': if isinstance(kw['HTRF_Old_Line'], basestring): if kw['HTRF_Old_Line'] != u'': htrf_lines.append(kw['HTRF_Old_Line']) else: htrf_lines += [ cell for cell in kw['HTRF_Old_Line'] if cell != u'' ] if not ct_lines: flash(l_(u'At least 1 CT_Line is required'), 'error') redirect(come_from) if not fp_lines: flash(l_(u'At least 1 FP_Line is required'), 'error') redirect(come_from) if not htrf_lines: flash(l_(u'At least 1 HTRF_Line is required'), 'error') redirect(come_from) #edit project name: if project.name != kw['name']: #change group name: gr = DBSession.query(Group).filter_by( group_name=project.name).first() gr.group_name = kw['name'] gr.display_name = kw['name'] #change permission name: perm = DBSession.query(Permission).filter( Permission.permission_name == project.name).first() perm.permission_name = kw['name'] project.name = kw['name'] #add description: if 'description' in kw and kw['description'] != u'' and kw[ 'description'] != project.description: project.description = kw['description'] #add cell lines import pickle if ct_lines: pickle_dump1 = pickle.dumps(ct_lines) ct_test = [ test for test in project.tests if test.name == 'CT' ][0] ct_test.cell_line = pickle_dump1 if fp_lines: pickle_dump2 = pickle.dumps(fp_lines) fp_test = [ test for test in project.tests if test.name == 'FP' ][0] fp_test.cell_line = pickle_dump2 if htrf_lines: pickle_dump3 = pickle.dumps(htrf_lines) htrf_test = [ test for test in project.tests if test.name == 'HTRF' ][0] htrf_test.cell_line = pickle_dump3 DBSession.flush() flash(l_(u'Task completed successfully')) redirect(come_from) else: flash(l_(u'Name is required'), 'error') redirect(come_from) return dict(page='index', userid=userid, project=project, come_from=come_from) @require( Any(is_user('manager'), has_permission('manage'), msg='Permission denied')) @expose('') def delete_project(self, *args, **kw): try: project_id = args[0] except Exception: redirect("/error") try: come_from = request.headers['Referer'] except Exception: come_from = request.path_url project = DBSession.query(Projects).get(project_id) if project: DBSession.delete(project) else: flash(l_(u'Project error'), 'error') redirect(come_from) flash(l_(u'Task completed successfully')) redirect(come_from)