def password_reset(request): email = request.params.get('email') try: session = DBSession() user = DBSession.query(User).filter_by(email=email).one() ptoken = DBSession.query(PasswordResetToken).get(user.id) if not ptoken: ptoken = PasswordResetToken(user_id=user.id) token = str(uuid4()) ptoken.token = token session.add(ptoken) except NoResultFound: token = None if token: # settings = request.registry.settings mailer = get_mailer(request) headers = {"header": u'Password reset', "message": u'Please click on the link bellow to reset your penelope account\'s password.', "link": '%s/change_password?token=%s' % (request.application_url, token), "action": 'Reset password'} message = Message(subject=u"Password reset request", recipients=[email], body=u'Password reset', extra_headers={'X-MC-Template': 'general', 'X-MC-MergeVars': json.dumps(headers)}) mailer.send(message) return {'request': request, 'token': token}
def test_password_set(self): email = u'*****@*****.**' self.add_user(email) session = DBSession() self.assertEqual(session.query(User).filter_by(email=email).one().password, None) token = self.generate_token(email)['token'] from por.dashboard.security.views import change_password request = Request(method='POST', params={'token': token, 'password': '******', 'password_repeat': 'topsecret'}) response = change_password(request) self.assertEqual(response.headers.get('Location'),'/login_form') self.assertNotEqual(session.query(User).filter_by(email=email).one().password, None)
def render(self): result = {} result['main_template'] = get_renderer( 'por.dashboard:skins/main_template.pt').implementation() result['main'] = get_renderer( 'por.dashboard.forms:templates/master.pt').implementation() schema = WizardSchema().clone() wizard_fanstatic.need() form = WizardForm(schema, formid='wizard', method='POST', buttons=[ SubmitButton(title=u'Submit'), ResetButton(title=u'Reset'), ]) form['new_users'].widget = SequenceWidget() form['users'].widget = SequenceWidget(min_len=1) users = DBSession.query(User).order_by(User.fullname) form['users']['user']['usernames'].widget.values = [('', '')] + \ [(str(u.id), u.fullname) for u in users] roles = DBSession.query(Role).order_by(Role.name) form['users']['user']['role'].widget.values = [('', '')] + \ [(str(role.id), role.name) for role in roles] form['new_users']['new_user']['role'].widget.values = [('', '')] + \ [(str(role.id), role.name) for role in roles] form['milestones'].widget = SequenceWidget(min_len=1) form['contracts'].title = '' form['contracts']['customer_requests'].widget = SequenceWidget(min_len=2) controls = self.request.POST.items() if controls != []: try: appstruct = form.validate(controls) self.handle_save(form, appstruct) except ValidationFailure as e: result['form'] = e.render() return result appstruct = {} appstruct['contracts'] ={'customer_requests': []} appstruct['contracts']['customer_requests'].append({'ticket': True, 'title': u'Analisi'}) appstruct['contracts']['customer_requests'].append({'ticket': True, 'title': u'Supporto'}) result['form'] = form.render(appstruct=appstruct) return result
def test_token_store_cleanup(self): email = u'*****@*****.**' self.add_user(email) self.generate_token(email)['token'] token2 = self.generate_token(email)['token'] session = DBSession() self.assertEqual(len(session.query(PasswordResetToken).join(User).filter(User.email == email).all()),1) from por.dashboard.security.views import change_password request = Request(method='POST', params={'token': token2, 'password': '******', 'password_repeat': 'topsecret'}) response = change_password(request) self.assertEqual(response.headers.get('Location'),'/login_form') self.assertEqual(len(session.query(PasswordResetToken).join(User).filter(User.email == email).all()),0)
def test_project_modification_date(self): project_name = u'C project' session = DBSession() project = Project(name=project_name) session.add(project) transaction.commit() project = session.query(Project).filter_by(name=project_name).first() old_date = project.modification_date project.name = u'A modified project' time.sleep(0.1) transaction.commit() project = session.query(Project).filter_by(name=u'A modified project').first() new_date = project.modification_date self.assertNotEqual(old_date, new_date)
def timeentry_crstate_validation_errors(project_id, tickets, request): # XXX this check is deactivated for now (see #312) return [] project = DBSession.query(Project).get(project_id) customer_requests = ticket_store.get_requests_from_tickets(project, tickets, request=request) for ticket_id, cr_id in customer_requests: cr = DBSession.query(CustomerRequest).get(cr_id) if cr.workflow_state != 'estimated': return ['Customer Request is not estimated'] return []
def report_index(context, request): users = DBSession.query(User).order_by(User.fullname) users = filter_users_with_timeentries(users) projects = sorted(request.filter_viewables(qry_active_projects()), key=unicodelower) customers = sorted(set(p.customer for p in projects), key=unicodelower) current_uid = request.authenticated_user.id saved_queries = DBSession.query(SavedQuery).filter(SavedQuery.author_id==current_uid) return { 'users': users, 'customers': customers, 'projects': projects, 'saved_queries': saved_queries.all() }
def unusedEmail(value): user = DBSession.query(User.id).filter(User.email == value).first() if user: return "email '%s' is already associated to another user" % \ value else: return True
def search(self, limit, author_id, project_id, date_from, date_to, searchtext): qry = DBSession.query(TimeEntry) qry = qry.filter(TimeEntry.author_id==author_id) if project_id is not colander.null: qry = qry.filter(TimeEntry.project_id==project_id) if date_from is not colander.null: qry = qry.filter(TimeEntry.date>=date_from) if date_to is not colander.null: qry = qry.filter(TimeEntry.date<=date_to) if searchtext is not colander.null: qry = qry.filter(TimeEntry.description.ilike(u'%{0}%'.format(searchtext))) qry = qry.order_by(sa.desc(TimeEntry.date), sa.desc(TimeEntry.start), sa.desc(TimeEntry.creation_date)) if limit: qry = qry.limit(limit) qry = self.request.filter_viewables(qry) entries_by_date = [] entries_count = 0 for k, g in itertools.groupby(qry, operator.attrgetter('date')): g = list(g) entries_by_date.append((k, g)) entries_count += len(g) return entries_by_date, entries_count
def latest_entries(context, request): """ Returns an HTML fragment with tables of the latest time entries """ qry = DBSession.query(TimeEntry) current_user = request.environ.get('repoze.who.identity')['user'] qry = qry.filter(TimeEntry.author_id==current_user.id) qry = qry.order_by(sa.desc(TimeEntry.date), sa.desc(TimeEntry.start), sa.desc(TimeEntry.creation_date)) time_entries_today = qry.filter(TimeEntry.date==datetime.date.today()).all() today_total = timedelta_as_human_str(sum([a.hours for a in time_entries_today], datetime.timedelta())) latest_limit = 20 time_entries_latest = qry.limit(latest_limit) return { 'context': context, 'request': request, 'time_entries_today': time_entries_today, 'today_total': today_total, 'time_entries_latest': time_entries_latest, 'time_entries_latest_limit': latest_limit, 'report_my_from_date': datetime.date.today() - datetime.timedelta(days=6), 'today': datetime.date.today(), }
def get_user_by_openid(request, openid): """ This method search for user using one of the possible user openids """ session = DBSession() if not isinstance(openid, basestring): return { 'status:': False, 'message': u'Openid parameter must be a string!', } try: user = session.query(User).join('openids').filter_by(openid=openid).one() except orm_exc.NoResultFound: return { 'status': False, 'message': u'No user found in db for %s openid' % openid, } return { 'status': True, 'message': u'User found.', 'email': user.email, 'login': user.login, 'openids': [x.openid for x in user.openids], }
def get_user_by_email(request, email): """ This method search for user using his email address """ session = DBSession() if not isinstance(email, basestring): return { 'status:': False, 'message': u'Email parameter must be a string!', } try: user = session.query(User).filter_by(email=email).one() except orm_exc.NoResultFound: return { 'status': False, 'message': u'No user found in db for %s mail address' % email, } return { 'status': True, 'message': u'User found.', 'email': user.email, 'login': user.login, 'openids': [x.openid for x in user.openids] }
def get_project_by_name(request, project_name): """ This method search for project by name """ session = DBSession() if not isinstance(project_name, basestring): return { 'status:': False, 'message': u'Project name parameter must be a string!', } try: project = session.query(Project).filter_by(name=project_name).one() except orm_exc.NoResultFound: return { 'status': False, 'message': u'No project found in db for %s name' % project_name, } return { 'status': True, 'message': u'Project found.', 'name': project.name, 'id': project.id, 'customer': project.customer.name, 'applications': [x.name for x in project.applications], 'customer_requests': [(x.id, x.name,) for x in project.customer_requests], }
def get_customer_by_name(request, customer_name): """ This method search for customer by name """ session = DBSession() if not isinstance(customer_name, basestring): return { 'status:': False, 'message': u'Customer name parameter must be a string!', } try: customer = session.query(Customer).filter_by(name=customer_name).one() except orm_exc.NoResultFound: return { 'status': False, 'message': u'No customer found in db for %s name' % customer_name, } return { 'status': True, 'message': u'Customer found.', 'name': customer.name, 'projects': [x.name for x in customer.projects], }
def state_contract_change(self): new_state = self.request.POST['new_state'] new_contract = self.request.POST['new_contract'] invoice_number = self.request.POST['invoice_number'] te_ids = set(int(s[3:]) for s, checkbox_state in self.request.POST.iteritems() if s.startswith('te_') and checkbox_state=='on') qry = DBSession.query(TimeEntry).filter(TimeEntry.id.in_(te_ids)) done_state = set() done_contract = set() errors = {} for te in qry: if new_state: try: workflow = get_workflow(te, te.__class__.__name__) workflow.transition_to_state(te, self.request, new_state, skip_same=True) done_state.add(te.id) if new_state == 'invoiced' and invoice_number: te.invoice_number = invoice_number except WorkflowError as msg: errors[te.id] = msg if new_contract: done_contract.add(te.id) te.contract_id = new_contract return done_state, done_contract, errors
def add_tickets(self, project, customerrequest, tickets, reporter, notify=False): from trac.env import Environment from trac.ticket.notification import TicketNotifyEmail from trac.ticket.model import Ticket from trac.util.text import exception_to_unicode from por.models.dashboard import User settings = get_current_registry().settings tracenvs = settings.get('por.trac.envs') request = get_current_request() for trac in project.tracs: for t in tickets: owner = DBSession.query(User).get(t['owner']) ticket = {'summary': t['summary'], 'description': t['description'], 'customerrequest': customerrequest.id, 'reporter': reporter.email, 'type': 'task', 'priority': 'major', 'milestone': 'Backlog', 'owner': owner.email, 'status': 'new'} tracenv = Environment('%s/%s' % (tracenvs, trac.trac_name)) tracenv.abs_href.base = trac.api_uri t = Ticket(tracenv) t.populate(ticket) t.insert() if notify: try: tn = TicketNotifyEmail(tracenv) tn.notify(t, newticket=True) except Exception, e: request.add_message('Failure sending notification on creation ' 'of a ticket #%s: %s' % (t.id, exception_to_unicode(e)), 'error')
def create_initial_application_acl(mapper, connection, target): if target.application_type == SVN: acl_rules = [ ("internal_developer", "edit"), ("internal_developer", "view"), ("external_developer", "edit"), ("external_developer", "view"), ] else: acl_rules = [ ("internal_developer", "view"), ("external_developer", "view"), ("secretary", "view"), ("secretary", "edit"), ] if target.application_type == "trac": acl_rules.append(("customer", "view")) for role_id, permission_name in acl_rules: acl = DBSession.query(ApplicationACL).get((target.id, role_id, permission_name)) if not acl: acl = ApplicationACL(application_id=target.id, role_id=role_id, permission_name=permission_name) DBSession.add(acl) else: # XXX this should not happen. pass
def test_add_project(self): project_name = u'A project' session = DBSession() project = Project(name=project_name) session.add(project) transaction.commit() self.assertEqual(session.query(Project).filter_by(name=project_name).first().name, 'A project')
def project_tree(context, request): """ This view is used by the customer-project-request javascript filter. """ all_projects = request.filter_viewables(DBSession.query(Project)) all_projects = [ project for project in request.filter_viewables(qry_active_projects()) if request.has_permission('reports_all_entries_for_project', project) ] customers = request.filter_viewables(set(p.customer for p in all_projects if p.active)) return [ { 'id': str(c.id), 'name': c.name, 'projects': [ { 'id': str(p.id), 'name': p.name, 'customer_requests': [ { 'id': str(cr.id), 'name': cr.name, } for cr in p.customer_requests ], } for p in c.projects if p in all_projects ] } for c in customers ]
def smartadd_projects(self): """ Returns a json list of project tags """ qry = self.request.filter_viewables(DBSession.query(Project).filter(Project.active)) projects = sorted((u'%s - %s' % (p.name, p.customer.name) for p in qry), key=unicodelower) return projects
def activate_iteration(context, request): docid = request.params.get('docid') if not docid: return view_iterations(context, request, validation_error=u'Missing document_id') #query = gdata.spreadsheet.service.CellQuery() #first take project names #query['min-col'] = '3' #query['max-col'] = '3' #query['min-row'] = '5' #cr_raw = get_cell_values(request, query) session = DBSession() #deactivate all CR #for cr in session.query(CustomerRequest): # cr.active = False #activate selected CR #cr_ids = set([item for sublist in [a.split(',') for a in cr_raw] for item in sublist]) #crs = session.query(CustomerRequest).filter(CustomerRequest.id.in_(cr_ids)) #for cr in crs: # cr.active = True gc = session.query(GlobalConfig).get(1) gc.active_iteration_url = docid return manage_iterations(context,request)
def test_add_application_with_sa_to_project(self): session = DBSession() project = Project(name=u'My project 1') application = Application(name=u'Trac') project.add_application(application) session.add(project) transaction.commit() self.assertEqual(session.query(Project).filter_by(name=u'My project 1').first().applications[0].name, u'Trac')
def test_add_application_to_project(self): session = DBSession() project = Project(name=u'My project 2') application = Application(name=u'Trac', api_uri='http://simple.api.uri') project.add_application(application) session.add(project) transaction.commit() self.assertEqual(session.query(Project).filter_by(name=u'My project 2').first().applications[0].name, u'Trac')
def test_project_creation_date(self): session = DBSession() project = Project(name=u'My first project A') session.add(project) transaction.commit() self.assertEqual(session.query(Project)\ .filter_by(name=u'My first project A')\ .first().creation_date.strftime('%Y%m%d'), datetime.now().strftime('%Y%m%d'))
def search(request): schema = SearchSchema().bind(request=request) form = PorInlineForm( schema, formid='search', method='GET', buttons=[SearchButton(title=u'Search'),] ) tracs = searchable_tracs(request) form['tracs'].widget.values = [('', '')] \ + [(t.trac_name, t.project_name) for t in tracs] users = DBSession.query(User).order_by(User.fullname) form['authors'].widget.values = [('', '')] \ + [(a.email, a.fullname) for a in users] controls = request.GET.items() if not controls: return {'form': form.render(), 'results':[]} try: appstruct = form.validate(controls) except deform.ValidationFailure as e: return {'form': e.render(), 'results':[]} params = appstruct.copy() if not params['tracs']: params['tracs'] = [t.trac_name for t in tracs] fs = FullTextSearch(request=request, **params) results = fs.get_search_results() next_url = None previous_url = None docs = [] if results: docs = [FullTextSearchObject(**doc) for doc in results] records_len = results.result.numFound if not fs.page_start + fs.page_size >= records_len: # end of set next_query = add_param(request, 'page_start', fs.page_start + fs.page_size) next_url = current_route_url(request, _query=next_query) if not fs.page_start == 0: previous_page = fs.page_start - fs.page_size if previous_page < 0: previous_page = 0 previous_query = add_param(request, 'page_start', previous_page) previous_url = current_route_url(request, _query=previous_query) return {'docs': docs, 'next': next_url, 'form': form.render(appstruct=appstruct), 'previous': previous_url, 'add_param': add_param, 'results': results}
def ticket_provider(project_id): if project_id: project = DBSession.query(Project).get(project_id) return [ t['id'] for t in ticket_store.get_tickets_for_project(project=project, not_invoiced=True, request=self.request) ]
def save_query(context, request): current_uid = request.authenticated_user.id query_meta = cgi.parse_qs(request.POST['query_meta']) if not 'query_name' in query_meta: return Response(u"Please specify a query name.", status=409) query_name = query_meta['query_name'][0] taken = DBSession.query(SavedQuery).filter(SavedQuery.author_id==current_uid).filter(SavedQuery.query_name==query_name).count() submit_type = request.POST['submit_type'] if submit_type == 'submit_edit': if taken: return Response(u"Name already in use: '%s'." % query_name, status=409) sq_id = query_meta['sq_id'][0] qry = DBSession.query(SavedQuery) qry = qry.filter(SavedQuery.author_id==current_uid) qry = qry.filter(SavedQuery.id==sq_id) sq = qry.one() sq.query_name = query_name return Response(u"The query has been renamed as '%s'." % query_name) elif submit_type == 'submit_delete': sq_id = query_meta['sq_id'][0] qry = DBSession.query(SavedQuery) qry = qry.filter(SavedQuery.author_id==current_uid) qry = qry.filter(SavedQuery.id==sq_id) sq = qry.one() DBSession.delete(sq) return Response(u"The saved query has been deleted.") elif submit_type == 'submit_add': if taken: return Response(u"Name already in use: '%s'." % query_name, status=409) # add sq = SavedQuery(query_name=query_name, report_name=query_meta['report_name'][0], query_string=request.POST['query_string'], author_id = current_uid) DBSession.add(sq) return Response(u"The query has been saved as '%s'." % query_name)
def smartadd_tickets(self): """ Returns a json list of ticket tags """ qry = self.request.filter_viewables(DBSession.query(Project).filter(Project.active)) projects = dict(('%s - %s' % (p.name, p.customer.name), p.id) for p in qry) text = self.request.params['text'] parser = SmartAddParser(text, projects=projects, request=self.request) if parser.TAG_TICK in parser.unparsed: ticket_search = parser.unparsed.split(parser.TAG_TICK)[-1] else: ticket_search = '' if ticket_search.isdigit(): # ^= is startswith (http://trac.edgewall.org/wiki/TracQuery) query = ['id^=%s' % ticket_search] elif ticket_search: query = ['summary~=%s' % ticket_search] else: query = None if parser.project_id: project = DBSession.query(Project).get(parser.project_id) tickets = ticket_store.get_tickets_for_project( project=project, request=self.request, query=query, not_invoiced=True, limit=15) else: tickets = [] return [ "%(id)s %(summary)s" % ticket for ticket in tickets if ticket['resolution'] not in ('invalid', 'duplicate') ]
def report_te_detail(context, request): ids = map(int, request.params['ids'].split(',')) qry = DBSession.query(TimeEntry).filter(TimeEntry.id.in_(ids)).order_by(TimeEntry.id) projects = set(te.project for te in qry) for project in projects: if not request.has_permission('reports_all_entries_for_project', project): return HTTPForbidden() return { 'time_entries': qry.all(), 'ticket_url': ticket_url, }
def smartadd_submit(self): """ Receives a line of smart-add and performs validation/insertion. """ projects = dict( ('%s - %s' % (p.name, p.customer.name), p.id) for p in self.request.filter_viewables(DBSession.query(Project).filter(Project.active)) ) def ticket_provider(project_id): if project_id: project = DBSession.query(Project).get(project_id) return [ t['id'] for t in ticket_store.get_tickets_for_project(project=project, not_invoiced=True, request=self.request) ] parser = SmartAddParser(unicode(self.request.body, 'utf8', 'ignore'), projects=projects, available_tickets=ticket_provider, request=self.request) errors = parser.validation_errors() if errors: # XXX register appropriate exception handler return Response(' - '.join(errors), status_int=400) pte = parser.parsed_time_entry parsed_tickets = pte['tickets'] ticket_summaries = [] entry_durations = list(time_chunks(pte['hours'], len(parsed_tickets))) for parsed_ticket, duration in zip(parsed_tickets, entry_durations): date = pte.get('date') or datetime.date.today() te = TimeEntry(date = date, start = pte['start'], end = pte['start'], description = pte['description'], ticket = parsed_ticket, project_id = pte['project_id'], hours = duration, ) te.request = self.request #bind for user calculation DBSession.add(te) # retrieve ticket descriptions (another trip to the store..) ticket_summaries.append( '#%s (%s)' % (te.ticket, ticket_store.get_ticket(self.request, te.project_id, te.ticket)[3]['summary']) ) return Response(u'Added to ticket(s) %s' % ', '.join(ticket_summaries))