Exemple #1
0
    def send_html(cls, to, topic, message):
        config = ApplicationConfig.get_current_config()

        email = MIMEMultipart('alternative')
        email['Subject'] = topic
        email['From'] = config.google_user_email
        email['To'] = to
        email.attach(MIMEText(message,'html', 'utf-8'))

        formatted_mail = email.as_string()

        messageFile = StringIO(formatted_mail)

        resultDeferred = Deferred()

        senderFactory = ESMTPSenderFactory(
            config.google_user_email, # user
            config.google_user_password, # secret
            config.google_user_email, # from
            to, # to
            messageFile, # message
            resultDeferred, # deferred
            contextFactory=cls.contextFactory)

        reactor.connectTCP(cls.SMTP_SERVER, cls.SMTP_PORT, senderFactory)
        return resultDeferred
Exemple #2
0
    def action(self):
        config_obj = ApplicationConfig.get_current_config()
        cleaning_time_presence = int(config_obj.cleaning_time_presence)

        today = datetime.datetime.now().date()
        date = today - datetime.timedelta(days=cleaning_time_presence)
        date = datetime.datetime.combine(date, day_end)
        cleaned = self.session.execute("""
            DELETE FROM presence_entry as p
            WHERE p.ts <= :date
            AND p.ts > (
                SELECT MIN(a.ts) FROM presence_entry a
                WHERE date_trunc('day', a.ts) = date_trunc('day', p.ts)
                AND a.user_id = p.user_id
            ) AND p.ts < (
                SELECT MAX(b.ts) FROM presence_entry b
                WHERE date_trunc('day', b.ts) = date_trunc('day', p.ts)
                AND b.user_id = p.user_id
            );
        """,
                                       params={
                                           'date': date
                                       }).rowcount
        LOG(u"Cleaned %s entries" % (cleaned, ))
        return Response(self._(u"Cleaned ${num} entries", num=cleaned))
Exemple #3
0
    def action(self):
        config_obj = ApplicationConfig.get_current_config()
        cleaning_time_presence = int(config_obj.cleaning_time_presence)

        today = datetime.datetime.now().date()
        date = today - datetime.timedelta(days=cleaning_time_presence)
        end_date = datetime.datetime.combine(date, day_end)
        start_date = end_date - datetime.timedelta(days=cleaning_time_presence * 3)
        cleaned = DBSession.execute(
            """
            WITH minq as
            (
                SELECT MIN(p1.id) FROM presence_entry as p1
                WHERE p1.ts >= :start_date AND p1.ts <= :end_date
                GROUP BY p1.user_id, date_trunc('day', p1.ts)
            ),
            maxq as
            (
                SELECT MAX(p2.id) FROM presence_entry as p2
                WHERE p2.ts >= :start_date AND p2.ts <= :end_date
                GROUP BY p2.user_id, date_trunc('day', p2.ts)
            )
            DELETE FROM presence_entry as p
            WHERE p.ts >= :start_date AND p.ts <= :end_date
            AND p.id NOT IN (SELECT * FROM minq) AND p.id NOT IN (SELECT * FROM maxq);
        """,
            params={"start_date": start_date, "end_date": end_date},
        ).rowcount
        LOG(u"Cleaned %s entries" % (cleaned,))
        return Response(self._(u"Cleaned ${num} entries", num=cleaned))
Exemple #4
0
    def send_with_file(cls, to, topic, message, file_path):
        config = ApplicationConfig.get_current_config()

        email = MIMEMultipart()
        email['Subject'] = topic
        email['From'] = config.google_user_email
        email['To'] = to

        part = MIMEBase('application', "octet-stream")
        part.set_payload(open(file_path, "rb").read())
        Encoders.encode_base64(part)

        part.add_header('Content-Disposition', 'attachment; filename="%s"' % file_path.split('/')[-1])

        email.attach(part)
        email.attach(MIMEText(message))

        formatted_mail = email.as_string()

        messageFile = StringIO(formatted_mail)

        resultDeferred = Deferred()

        senderFactory = ESMTPSenderFactory(
            config.google_user_email, # user
            config.google_user_password, # secret
            config.google_user_email, # from
            to, # to
            messageFile, # message
            resultDeferred, # deferred
            contextFactory=cls.contextFactory)

        reactor.connectTCP(cls.SMTP_SERVER, cls.SMTP_PORT, senderFactory)
        return resultDeferred
Exemple #5
0
 def action(self):
     date = datetime.date.today() - relativedelta(days=1)
     config_obj = ApplicationConfig.get_current_config()
     self._today_hours_without_ticket(
         date, config_obj.reports_without_ticket_project_ids, config_obj.reports_without_ticket_omit_user_ids
     )
     return Response("ok")
Exemple #6
0
    def _annually_report(self, year):
        year_start = datetime.date(year, 1, 1)
        year_end = datetime.date(year, 12, 31)
        excuses_error = None
        config_obj = ApplicationConfig.get_current_config()
        query = DBSession.query('uid', 'date', 'presence').from_statement("""
        SELECT p.user_id as "uid",
               date_trunc('day', p.ts) as "date",
               MIN(p.ts) as "presence"
        FROM presence_entry p
        WHERE p.ts >= :year_start AND
              p.ts <= :year_end
        GROUP BY p.user_id, date_trunc('day', p.ts)
        """).params(year_start=year_start, year_end=year_end)
        data = query.all()
        users = User.query.filter(User.is_active==True)\
                          .filter(User.is_not_client())\
                          .filter(User.is_not_freelancer())\
                          .order_by(User.name).all()

        _excuses = excuses.presence()

        data = self._group_by_user_monthly(data, _excuses)
        stats = self._prepare_statistics(data)

        return dict(
            data=data,
            users=users,
            stats=stats,
            today=datetime.datetime.today(),
            year_start=year_start,
            deltazero=deltazero,
            late_limit=config_obj.monthly_late_limit,
            excuses_error=excuses_error,
        )
Exemple #7
0
    def action(self):
        config_obj = ApplicationConfig.get_current_config()
        cleaning_time_presence = int(config_obj.cleaning_time_presence)

        today = datetime.datetime.now().date()
        date = today - datetime.timedelta(days=cleaning_time_presence)
        end_date = datetime.datetime.combine(date, day_end)
        start_date = end_date - datetime.timedelta(
            days=cleaning_time_presence * 3, )
        cleaned = DBSession.execute("""
            WITH minq as
            (
                SELECT MIN(p1.id) FROM presence_entry as p1
                WHERE p1.ts >= :start_date AND p1.ts <= :end_date
                GROUP BY p1.user_id, date_trunc('day', p1.ts)
            ),
            maxq as
            (
                SELECT MAX(p2.id) FROM presence_entry as p2
                WHERE p2.ts >= :start_date AND p2.ts <= :end_date
                GROUP BY p2.user_id, date_trunc('day', p2.ts)
            )
            DELETE FROM presence_entry as p
            WHERE p.ts >= :start_date AND p.ts <= :end_date
            AND p.id NOT IN (SELECT * FROM minq) AND p.id NOT IN (SELECT * FROM maxq);
        """,
                                    params={
                                        'start_date': start_date,
                                        'end_date': end_date
                                    }).rowcount
        LOG(u"Cleaned %s entries" % (cleaned, ))
        return Response(self._(u"Cleaned ${num} entries", num=cleaned))
Exemple #8
0
    def send_html(cls, to, topic, message):
        config = ApplicationConfig.get_current_config()

        email = MIMEMultipart('alternative')
        email['Subject'] = topic
        email['From'] = config.google_user_email
        email['To'] = to
        email.attach(MIMEText(message,'html', 'utf-8'))

        formatted_mail = email.as_string()

        messageFile = StringIO(formatted_mail)

        resultDeferred = Deferred()

        senderFactory = ESMTPSenderFactory(
            config.google_user_email, # user
            config.google_user_password, # secret
            config.google_user_email, # from
            to, # to
            messageFile, # message
            resultDeferred, # deferred
            contextFactory=cls.contextFactory)

        reactor.connectTCP(cls.SMTP_SERVER, cls.SMTP_PORT, senderFactory)
        return resultDeferred
Exemple #9
0
    def send_with_file(cls, to, topic, message, file_path):
        config = ApplicationConfig.get_current_config()

        email = MIMEMultipart()
        email['Subject'] = topic
        email['From'] = config.google_user_email
        email['To'] = to

        part = MIMEBase('application', "octet-stream")
        part.set_payload(open(file_path, "rb").read())
        Encoders.encode_base64(part)

        part.add_header('Content-Disposition', 'attachment; filename="%s"' % file_path.split('/')[-1])

        email.attach(part)
        email.attach(MIMEText(message))

        formatted_mail = email.as_string()

        messageFile = StringIO(formatted_mail)

        resultDeferred = Deferred()

        senderFactory = ESMTPSenderFactory(
            config.google_user_email, # user
            config.google_user_password, # secret
            config.google_user_email, # from
            to, # to
            messageFile, # message
            resultDeferred, # deferred
            contextFactory=cls.contextFactory)

        reactor.connectTCP(cls.SMTP_SERVER, cls.SMTP_PORT, senderFactory)
        return resultDeferred
Exemple #10
0
 def __init__(self):
     config = ApplicationConfig.get_current_config()
     user = config.google_user_email
     secret = config.google_user_password
     self.user, self.secret = user, secret
     self.server = smtplib.SMTP(self.HOST, self.PORT)
     self.server.ehlo()
     self.server.starttls()
     self.server.login(user, secret)
Exemple #11
0
 def action(self):
     date = datetime.date.today() - relativedelta(days=1)
     config_obj = ApplicationConfig.get_current_config()
     self._today_hours_without_ticket(
         date,
         config_obj.reports_without_ticket_project_ids,
         config_obj.reports_without_ticket_omit_user_ids,
     )
     return Response('ok')
Exemple #12
0
 def __init__(self):
     config = ApplicationConfig.get_current_config()
     user = config.google_user_email
     secret = config.google_user_password
     self.user, self.secret = user, secret
     self.server = smtplib.SMTP(self.HOST, self.PORT)
     self.server.ehlo()
     self.server.starttls()
     self.server.login(user, secret)
Exemple #13
0
def callback(request):
    code = request.params.get('code', '')
    try:
        credentials = flow.step2_exchange(code)
    except FlowExchangeError:
        raise HTTPForbidden
    data = requests.get(USER_INFO_URI % credentials.access_token, verify=False)
    google_profile = data.json

    email = google_profile['email']

    EXTRA_EMAILS = request.registry.settings.get('GOOGLE_EXTRA_EMAILS', '').split('\n')
    config = ApplicationConfig.get_current_config(allow_empty=True)
    freelancers = config.get_freelancers()
    clients_emails = Client.get_emails()
    if email.endswith('@%s' % request.registry.settings['COMPANY_DOMAIN']) or email in EXTRA_EMAILS:
        group = 'user'
    elif email in freelancers:
        group = 'freelancer'
    elif email in clients_emails:
        group = 'client'
    else:
        WARN_LOG(u"Forbidden acccess for profile:\n%s\n client's emails:\n%s\nfreelancer's emails:\n%s" % (google_profile, clients_emails, freelancers))
        return HTTPForbidden()

    session = request.db_session
    user = session.query(User).filter(User.email==email).first()
    if user is not None:
        if credentials.refresh_token:
            DEBUG(u'Adding refresh token %s for user %s' % (
                credentials.refresh_token, user.name,
            ))
            user.refresh_token = credentials.refresh_token
            session.add(user)
        DEBUG(u'Signing in existing user %s' % (user.name, ))
    else:
        LOG(u'Creating new user with name %s and email %s, group: %s' % (google_profile['name'], google_profile['email'], group))
        user = User(
            name=google_profile['name'],
            email=email,
            refresh_token=credentials.refresh_token or '',
            groups=[group],
        )

        session.add(user)
        session.flush()
    headers = remember(request, user.id)
    DEBUG(u'User %s set' % user.name)
    if group == 'client':
        location = request.url_for('/scrum/sprint/list')
    else:
        location = '/'
    return HTTPFound(
        location=location,
        headers=headers,
    )
Exemple #14
0
    def _fetch_bugs_titles(self, tracker_ticket):
        query = self.session.query
        config_obj = ApplicationConfig.get_current_config()

        user = query(User).filter(
            User.id == config_obj.hours_ticket_user_id).first()
        tracker_creds = query(Tracker.id, Tracker, TrackerCredentials)\
                            .filter(TrackerCredentials.tracker_id==Tracker.id)\
                            .filter(TrackerCredentials.user_id==User.id)\
                            .filter(User.id==config_obj.hours_ticket_user_id)
        tracker_creds = groupby(tracker_creds, lambda x: x[0], lambda x: x[1:])

        fetchers = {}
        for tracker_id, ticket_ids in tracker_ticket.iteritems():
            ticket_ids = [ticket_id for ticket_id in ticket_ids if ticket_id]
            if not tracker_id in tracker_creds:
                continue
            tracker, creds = tracker_creds[tracker_id][0]
            mapping = {creds.login.lower(): user}
            for i, portion in enumerate(
                    partition(ticket_ids, MAX_TICKETS_PER_REQUEST)):
                fetcher = get_fetcher(tracker, creds, mapping)
                fetcher.fetch_bug_titles_and_depends_on(portion)
                fetchers[(tracker.name, i)] = fetcher

        ticket_titles = {}
        start = time()
        while len(fetchers):
            for key, fetcher in fetchers.iteritems():
                if fetcher.isReady():
                    if fetcher.error:
                        ERROR(u"Fetcher for tracker %s failed with %r" %
                              (key[0], fetcher.error))
                        del fetchers[key]
                        break  # continue ignoring exception - titles and depends_on will be empty
                        #raise fetcher.error
                    for bug_id, bug in fetcher.bugs.iteritems():
                        if type(bug['title']) == str:
                            ticket_titles['%s_%s' %
                                          (fetcher.tracker.id, bug_id
                                           )] = bug['title'].decode('utf-8')
                        else:
                            ticket_titles['%s_%s' % (fetcher.tracker.id,
                                                     bug_id)] = bug['title']
                    del fetchers[key]
                    break
            else:  # no fetcher is ready yet
                if time() - start > MAX_TIMEOUT:
                    ERROR(u'%s requests timed-out' % len(fetchers))
                    break  # continue without exception - titles and depends_on will be empty
                    # raise FetchException(u'%s requests timed-out for tracker %s' % (len(fetchers), tracker.name))
                else:
                    sleep(0.1)
        return ticket_titles
Exemple #15
0
    def __call__(self, *args, **kwargs):
        config = ApplicationConfig.get_current_config(allow_empty=True)
        if config is None:
            WARN(u'Application config not found, emails cannot be checked')
            return
        trackers = dict(
            (tracker.mailer, tracker)
                for tracker in Tracker.query.filter(Tracker.mailer != None).filter(Tracker.mailer != '')
        )
        if not len(trackers):
            WARN(u'No trackers have mailers configured, email will not be checked')
            return

        username = config.google_user_email.encode('utf-8')
        password = config.google_user_password.encode('utf-8')

        # TODO
        logins_mappings = dict(
            (tracker.id, TrackerCredentials.get_logins_mapping(tracker))
                for tracker in trackers.itervalues()
        )
        selector_mappings = dict(
            (tracker.id, SelectorMapping(tracker))
                for tracker in trackers.itervalues()
        )

        # find all projects connected to the tracker
        projects = dict(
            (project.id, project)
                for project in Project.query.all()
        )

        # all pre-conditions should be checked by now

        # start fetching
        fetcher = MailFetcher(
            username,
            password,
        )

        # ok, we have all mails, lets create timeentries from them
        extractor = TimeEntryMailExtractor(
            trackers,
            logins_mappings,
            projects,
            selector_mappings,
        )

        for msg in fetcher:
            timeentry = extractor.get(msg)
            if timeentry:
                DBSession.add(timeentry)
        transaction.commit()
Exemple #16
0
    def _fetch_bugs_titles(self, tracker_ticket):
        query = self.session.query
        config_obj = ApplicationConfig.get_current_config()

        user = query(User).filter(User.id == config_obj.hours_ticket_user_id).first()
        tracker_creds = (
            query(Tracker.id, Tracker, TrackerCredentials)
            .filter(TrackerCredentials.tracker_id == Tracker.id)
            .filter(TrackerCredentials.user_id == User.id)
            .filter(User.id == config_obj.hours_ticket_user_id)
        )
        tracker_creds = groupby(tracker_creds, lambda x: x[0], lambda x: x[1:])

        fetchers = {}
        for tracker_id, ticket_ids in tracker_ticket.iteritems():
            ticket_ids = [ticket_id for ticket_id in ticket_ids if ticket_id]
            if not tracker_id in tracker_creds:
                continue
            tracker, creds = tracker_creds[tracker_id][0]
            mapping = {creds.login.lower(): user}
            for i, portion in enumerate(partition(ticket_ids, MAX_TICKETS_PER_REQUEST)):
                fetcher = get_fetcher(tracker, creds, mapping)
                fetcher.fetch_bug_titles_and_depends_on(portion)
                fetchers[(tracker.name, i)] = fetcher

        ticket_titles = {}
        start = time()
        while len(fetchers):
            for key, fetcher in fetchers.iteritems():
                if fetcher.isReady():
                    if fetcher.error:
                        ERROR(u"Fetcher for tracker %s failed with %r" % (key[0], fetcher.error))
                        del fetchers[key]
                        break  # continue ignoring exception - titles and depends_on will be empty
                        # raise fetcher.error
                    for bug_id, bug in fetcher.bugs.iteritems():
                        if type(bug["title"]) == str:
                            ticket_titles["%s_%s" % (fetcher.tracker.id, bug_id)] = bug["title"].decode("utf-8")
                        else:
                            ticket_titles["%s_%s" % (fetcher.tracker.id, bug_id)] = bug["title"]
                    del fetchers[key]
                    break
            else:  # no fetcher is ready yet
                if time() - start > MAX_TIMEOUT:
                    ERROR(u"%s requests timed-out" % len(fetchers))
                    break  # continue without exception - titles and depends_on will be empty
                    # raise FetchException(u'%s requests timed-out for tracker %s' % (len(fetchers), tracker.name))
                else:
                    sleep(0.1)
        return ticket_titles
    def __call__(self, *args, **kwargs):
        config = ApplicationConfig.get_current_config(allow_empty=True)
        if config is None:
            WARN(u'Application config not found, emails cannot be checked')
            return
        trackers = dict(
            (tracker.mailer, tracker) for tracker in Tracker.query.filter(
                Tracker.mailer != None).filter(Tracker.mailer != ''))
        if not len(trackers):
            WARN(
                u'No trackers have mailers configured, email will not be checked'
            )
            return

        username = config.google_user_email.encode('utf-8')
        password = config.google_user_password.encode('utf-8')

        # TODO
        logins_mappings = dict(
            (tracker.id, TrackerCredentials.get_logins_mapping(tracker))
            for tracker in trackers.itervalues())
        selector_mappings = dict((tracker.id, SelectorMapping(tracker))
                                 for tracker in trackers.itervalues())

        # find all projects connected to the tracker
        projects = dict(
            (project.id, project) for project in Project.query.all())

        # all pre-conditions should be checked by now

        # start fetching
        fetcher = MailFetcher(
            username,
            password,
        )

        # ok, we have all mails, lets create timeentries from them
        extractor = TimeEntryMailExtractor(
            trackers,
            logins_mappings,
            projects,
            selector_mappings,
        )

        for msg in fetcher:
            timeentry = extractor.get(msg)
            if timeentry:
                DBSession.add(timeentry)
        transaction.commit()
Exemple #18
0
    def action(self):
        config_obj = ApplicationConfig.get_current_config()
        client = SpreadsheetConnector(config_obj.google_user_email, config_obj.google_user_password)
        worksheet = client.get_worksheet(config_obj.holidays_spreadsheet, 6)
        data = worksheet.FindRecords("")
        dates_new = set([datetime.datetime.strptime(d.content["data"], "%Y-%m-%d").date() for d in data])
        dates_old = set(Holiday.all(cache=False))
        dates_diff = dates_new.difference(dates_old)

        if dates_diff:
            holidays = [Holiday(date=date) for date in dates_diff]
            self.session.add_all(holidays)

        INFO(u"%s Holidays added: %s" % (len(dates_diff), dates_diff))
        return Response("ok")
Exemple #19
0
    def action(self):
        config_obj = ApplicationConfig.get_current_config()
        client = SpreadsheetConnector(config_obj.google_user_email, config_obj.google_user_password)
        worksheet = client.get_worksheet(config_obj.holidays_spreadsheet, 6)
        data = worksheet.GetRecords(1, 99999)  # Magic Constant
        dates_new = set([ datetime.datetime.strptime(d.content['data'], '%Y-%m-%d').date() for d in data ])
        dates_old = set(Holiday.all(cache=False))
        dates_diff = dates_new.difference(dates_old)

        if dates_diff:
            holidays = [ Holiday(date=date) for date in dates_diff ]
            DBSession.add_all(holidays)

        INFO(u'%s Holidays added: %s' % (len(dates_diff), dates_diff))
        return Response('ok')
Exemple #20
0
 def _synchronize_client_hours(self):
     LOG(u"Client Hours synchronization starts")
     entries = self.session.query("month", "email", "client", "time").from_statement(
         """
         SELECT
             date_trunc('month', t.date) as "month",
             u.email as "email",
             c.name as client,
             COALESCE(SUM(t.time), 0) as "time"
         FROM
             time_entry t,
             project p,
             "user" u,
             client c
         WHERE
             t.deleted = FALSE AND
             t.project_id = p.id AND
             p.client_id = c.id AND
             t.user_id = u.id
         GROUP BY
             u.email,
             c.name,
             date_trunc('month', t.date)
         ORDER BY
             "month",
             "email",
             "client"
     """
     )
     rows = [
         (month.strftime("%Y-%m-%d"), client, email, (u"%.2f" % time).replace(".", ","))
         for month, email, client, time in entries
     ]
     config_obj = ApplicationConfig.get_current_config()
     h.trier(
         partial(
             gdocs.insert_or_replace_worksheet,
             config_obj.google_user_email,
             config_obj.google_user_password,
             config_obj.hours_employee_project,
             "DB-CLIENT",
             [u"Miesiac", u"Klient", u"Osoba", u"Liczba przepracowanych godzin", u"Miesiac (import)"],
             rows,
         ),
         doc=u"Client hours synchronization",
     )
     return u"Synchronized"
Exemple #21
0
 def _synchronize_client_hours(self):
     LOG(u"Client Hours synchronization starts")
     entries = self.session.query('month', 'email', 'client', 'time').from_statement("""
         SELECT
             date_trunc('month', t.date) as "month",
             u.email as "email",
             c.name as client,
             COALESCE(SUM(t.time), 0) as "time"
         FROM
             time_entry t,
             project p,
             "user" u,
             client c
         WHERE
             t.deleted = FALSE AND
             t.project_id = p.id AND
             p.client_id = c.id AND
             t.user_id = u.id
         GROUP BY
             u.email,
             c.name,
             date_trunc('month', t.date)
         ORDER BY
             "month",
             "email",
             "client"
     """)
     rows = [
     (month.strftime('%Y-%m-%d'), client, email, (u'%.2f' % time).replace('.', ','))
     for month, email, client, time in entries
     ]
     config_obj = ApplicationConfig.get_current_config()
     h.trier(
         partial(
             gdocs.insert_or_replace_worksheet,
             config_obj.google_user_email,
             config_obj.google_user_password,
             config_obj.hours_employee_project,
             'DB-CLIENT-test',
             [u'Miesiac', u'Klient', u'Osoba', u'Liczba przepracowanych godzin', u'Miesiac (import)'],
             rows
         ),
         doc=u"Client hours synchronization"
     )
     return u"Synchronized"
Exemple #22
0
    def _annually_report(self, year):
        year_start = datetime.date(year, 1, 1)
        year_end = datetime.date(year, 12, 31)
        excuses_error = None
        config_obj = ApplicationConfig.get_current_config()
        entries = DBSession.query('user_id', 'date').from_statement("""
        SELECT date_trunc('day', s.date) as date, s.user_id as user_id
        FROM time_entry s
        WHERE DATE(s.modified_ts) > s.date AND
              s.date >= :year_start AND
              s.date <= :year_end
        GROUP BY date_trunc('day', s.date), s.user_id
        """).params(year_start=year_start, year_end=year_end)

        users = User.query.filter(User.is_active==True)\
                          .filter(User.is_not_client())\
                          .order_by(User.is_freelancer(), User.name)

        entries_grouped = {}
        _excuses = excuses.wrongtime()

        for user_id, date in entries:
            month = date.month - 1
            entry = entries_grouped.setdefault(user_id, [0] * 12)
            if date.strftime('%Y-%m-%d') not in _excuses.get(user_id,
                                                             {}).keys():
                entry[month] += 1

        stats = {}

        for user_id, entry in entries_grouped.iteritems():
            stats_entry = stats.setdefault(user_id, [0])
            stats_entry[0] = sum(entry)

        return dict(
            entries=entries_grouped,
            stats=stats,
            users=users,
            year_start=year_start,
            limit=config_obj.monthly_incorrect_time_record_limit,
            excuses_error=excuses_error,
        )
Exemple #23
0
    def send(cls, to, topic, message, sender_name=None, cc=None, replay_to=None):
        """
        Send an email with message to given address.
        This is an asynchronous call.

        @return: deferred
        """
        config = ApplicationConfig.get_current_config()
        user = config.google_user_email
        email_addr = user
        if sender_name:
            email_addr = formataddr((sender_name, email_addr))
        secret = config.google_user_password
        SenderFactory = ESMTPSenderFactory

        email = MIMEText(message, _charset='utf-8')
        email['Subject'] = topic
        email['From'] = email_addr
        email['To'] = to
        if cc:
            email['Cc'] = cc

        if replay_to:
            email['Reply-To'] = replay_to

        formatted_mail = email.as_string()

        messageFile = StringIO(formatted_mail)

        resultDeferred = Deferred()

        senderFactory = SenderFactory(
            user, # user
            secret, # secret
            user, # from
            to, # to
            messageFile, # message
            resultDeferred, # deferred
            contextFactory=cls.contextFactory)

        reactor.connectTCP(cls.SMTP_SERVER, cls.SMTP_PORT, senderFactory)
        return resultDeferred
Exemple #24
0
    def send(cls, to, topic, message, sender_name=None, cc=None, replay_to=None):
        """
        Send an email with message to given address.
        This is an asynchronous call.

        @return: deferred
        """
        config = ApplicationConfig.get_current_config()
        user = config.google_user_email
        email_addr = user
        if sender_name:
            email_addr = formataddr((sender_name, email_addr))
        secret = config.google_user_password
        SenderFactory = ESMTPSenderFactory

        email = MIMEText(message, _charset='utf-8')
        email['Subject'] = topic
        email['From'] = email_addr
        email['To'] = to
        if cc:
            email['Cc'] = cc

        if replay_to:
            email['Reply-To'] = replay_to

        formatted_mail = email.as_string()

        messageFile = StringIO(formatted_mail)

        resultDeferred = Deferred()

        senderFactory = SenderFactory(
            user, # user
            secret, # secret
            user, # from
            to, # to
            messageFile, # message
            resultDeferred, # deferred
            contextFactory=cls.contextFactory)

        reactor.connectTCP(cls.SMTP_SERVER, cls.SMTP_PORT, senderFactory)
        return resultDeferred
Exemple #25
0
    def _annually_report(self, year):
        year_start = datetime.date(year, 1, 1)
        year_end = datetime.date(year, 12, 31)
        excuses_error = None
        config_obj = ApplicationConfig.get_current_config()
        entries = DBSession.query('user_id', 'date').from_statement("""
        SELECT date_trunc('day', s.date) as date, s.user_id as user_id
        FROM time_entry s
        WHERE DATE(s.modified_ts) > s.date AND
              s.date >= :year_start AND
              s.date <= :year_end
        GROUP BY date_trunc('day', s.date), s.user_id
        """).params(year_start=year_start, year_end=year_end)

        users = User.query.filter(User.is_active==True)\
                          .filter(User.is_not_client())\
                          .order_by(User.is_freelancer(), User.name)

        entries_grouped = {}
        _excuses = excuses.wrongtime()

        for user_id, date in entries:
            month = date.month - 1
            entry = entries_grouped.setdefault(user_id, [0]*12)
            if date.strftime('%Y-%m-%d') not in _excuses.get(user_id, {}).keys():
                entry[month] += 1

        stats = {}

        for user_id, entry in entries_grouped.iteritems():
            stats_entry = stats.setdefault(user_id, [0])
            stats_entry[0] = sum(entry)

        return dict(
            entries=entries_grouped,
            stats=stats,
            users=users,
            year_start=year_start,
            limit=config_obj.monthly_incorrect_time_record_limit,
            excuses_error=excuses_error,
        )
Exemple #26
0
    def _run(self):
        config = ApplicationConfig.get_current_config(allow_empty=True)
        if config is None:
            WARN(u'Application config not found, emails cannot be checked')
            return self.mark_not_busy()
        trackers = dict(
            (tracker.mailer, tracker)
                for tracker in Tracker.query.filter(Tracker.mailer != None).filter(Tracker.mailer != '')
        )
        if not len(trackers):
            WARN(u'No trackers have mailers configured, email will not be checked')
            return self.mark_not_busy()

        username = config.google_user_email.encode('utf-8')
        password = config.google_user_password.encode('utf-8')

        # TODO
        logins_mappings = dict(
            (tracker.id, TrackerCredentials.get_logins_mapping(tracker))
                for tracker in trackers.itervalues()
        )
        selector_mappings = dict(
            (tracker.id, SelectorMapping(tracker))
                for tracker in trackers.itervalues()
        )

        # find all projects connected to the tracker
        projects = dict(
            (project.id, project)
                for project in Project.query.all()
        )

        # all pre-conditions should be checked by now

        # start fetching
        f = CustomClientFactory(username, password, self.mark_not_busy,
            trackers, logins_mappings, projects, selector_mappings)
        f.protocol = MailerPOP3Client
        reactor.connectSSL(self.POP3_SERVER, self.POP3_PORT, f, self.context_factory)
Exemple #27
0
    def _run(self):
        config = ApplicationConfig.get_current_config(allow_empty=True)
        if config is None:
            WARN(u'Application config not found, emails cannot be checked')
            return self.mark_not_busy()
        trackers = dict(
            (tracker.mailer, tracker)
                for tracker in Tracker.query.filter(Tracker.mailer != None).filter(Tracker.mailer != '')
        )
        if not len(trackers):
            WARN(u'No trackers have mailers configured, email will not be checked')
            return self.mark_not_busy()

        username = config.google_user_email.encode('utf-8')
        password = config.google_user_password.encode('utf-8')

        # TODO
        logins_mappings = dict(
            (tracker.id, TrackerCredentials.get_logins_mapping(tracker))
                for tracker in trackers.itervalues()
        )
        selector_mappings = dict(
            (tracker.id, SelectorMapping(tracker))
                for tracker in trackers.itervalues()
        )

        # find all projects connected to the tracker
        projects = dict(
            (project.id, project)
                for project in Project.query.all()
        )

        # all pre-conditions should be checked by now

        # start fetching
        f = CustomClientFactory(username, password, self.mark_not_busy,
            trackers, logins_mappings, projects, selector_mappings)
        f.protocol = MailerPOP3Client
        reactor.connectSSL(self.POP3_SERVER, self.POP3_PORT, f, self.context_factory)
Exemple #28
0
    def action(self):
        config_obj = ApplicationConfig.get_current_config()
        cleaning_time_presence = int(config_obj.cleaning_time_presence)

        today = datetime.datetime.now().date()
        date = today - datetime.timedelta(days=cleaning_time_presence)
        date = datetime.datetime.combine(date, day_end)
        cleaned = self.session.execute("""
            DELETE FROM presence_entry as p
            WHERE p.ts <= :date
            AND p.ts > (
                SELECT MIN(a.ts) FROM presence_entry a
                WHERE date_trunc('day', a.ts) = date_trunc('day', p.ts)
                AND a.user_id = p.user_id
            ) AND p.ts < (
                SELECT MAX(b.ts) FROM presence_entry b
                WHERE date_trunc('day', b.ts) = date_trunc('day', p.ts)
                AND b.user_id = p.user_id
            );
        """, params= {'date': date}).rowcount
        LOG(u"Cleaned %s entries" % (cleaned, ))
        return Response(self._(u"Cleaned ${num} entries", num=cleaned))
Exemple #29
0
    def _annually_report(self, year):
        year_start = datetime.date(year, 1, 1)
        year_end = datetime.date(year, 12, 31)
        excuses_error = None
        config_obj = ApplicationConfig.get_current_config()
        query = self.session.query('uid', 'date', 'presence').from_statement("""
        SELECT p.user_id as "uid",
               date_trunc('day', p.ts) as "date",
               MIN(p.ts) as "presence"
        FROM presence_entry p
        WHERE p.ts >= :year_start AND
              p.ts <= :year_end
        GROUP BY p.user_id, date_trunc('day', p.ts)
        """).params(year_start=year_start, year_end=year_end)
        data = query.all()
        users = User.query.filter(User.is_active==True)\
                          .filter(User.is_not_client())\
                          .filter(User.freelancer==False)\
                          .order_by(User.name).all()

        _excuses = excuses.presence()


        data = self._group_by_user_monthly(data, _excuses)
        stats = self._prepare_statistics(data)

        return dict(
            data=data,
            users=users,
            stats=stats,

            today=datetime.datetime.today(),
            year_start=year_start,
            deltazero=deltazero,
            late_limit=config_obj.monthly_late_limit,
            excuses_error=excuses_error,
        )
Exemple #30
0
def callback(request):
    code = request.params.get('code', '')
    try:
        credentials = flow.step2_exchange(code)
    except FlowExchangeError:
        raise HTTPForbidden
    data = requests.get(USER_INFO_URI % credentials.access_token, verify=False)
    google_profile = data.json

    email = google_profile['email']

    EXTRA_EMAILS = request.registry.settings.get('GOOGLE_EXTRA_EMAILS',
                                                 '').split('\n')
    config = ApplicationConfig.get_current_config(allow_empty=True)
    freelancers = config.get_freelancers()
    clients_emails = Client.get_emails()
    if email.endswith('@%s' % request.registry.settings['COMPANY_DOMAIN']
                      ) or email in EXTRA_EMAILS:
        group = 'user'
    elif email in freelancers:
        group = 'freelancer'
    elif email in clients_emails:
        group = 'client'
    else:
        WARN_LOG(
            u"Forbidden acccess for profile:\n%s\n client's emails:\n%s\nfreelancer's emails:\n%s"
            % (google_profile, clients_emails, freelancers))
        return HTTPForbidden()

    session = request.db_session
    user = session.query(User).filter(User.email == email).first()
    if user is not None:
        if credentials.refresh_token:
            DEBUG(u'Adding refresh token %s for user %s' % (
                credentials.refresh_token,
                user.name,
            ))
            user.refresh_token = credentials.refresh_token
            session.add(user)
        DEBUG(u'Signing in existing user %s' % (user.name, ))
    else:
        LOG(u'Creating new user with name %s and email %s, group: %s' %
            (google_profile['name'], google_profile['email'], group))
        user = User(
            name=google_profile['name'],
            email=email,
            refresh_token=credentials.refresh_token or '',
            groups=[group],
        )

        session.add(user)
        session.flush()
    headers = remember(request, user.id)
    DEBUG(u'User %s set' % user.name)
    if group == 'client':
        location = request.url_for('/scrum/sprint/list')
    else:
        location = '/'
    return HTTPFound(
        location=location,
        headers=headers,
    )
Exemple #31
0
    def dispatch(self):
        subpage = self.request.GET.get('subpage', 'general')
        config_obj = ApplicationConfig.get_current_config(allow_empty=True)

        if config_obj is not None:
            LOG(u"Found config object from %s" % (config_obj.date, ))
            form = ConfigForm(self.request.POST, obj=config_obj)
        else:
            LOG(u"Config object not found")
            form = ConfigForm(self.request.POST)
        if self.request.method == 'POST' and form.validate():
            if config_obj is None:
                config_obj = ApplicationConfig()

            config_obj.office_ip = form.office_ip.data
            config_obj.google_user_email = form.google_user_email.data
            config_obj.google_user_password = form.google_user_password.data
            config_obj.holidays_spreadsheet = form.holidays_spreadsheet.data
            config_obj.cleaning_time_presence = form.cleaning_time_presence.data
            config_obj.hours_employee_project = form.hours_employee_project.data
            config_obj.absence_project_id = form.absence_project_id.data if form.absence_project_id.data else None
            config_obj.reports_project_ids = [
                int(id) for id in form.reports_project_ids.data
            ]
            config_obj.reports_omit_user_ids = [
                int(id) for id in form.reports_omit_user_ids.data
            ]
            config_obj.reports_without_ticket_project_ids = [
                int(id) for id in form.reports_without_ticket_project_ids.data
            ]
            config_obj.reports_without_ticket_omit_user_ids = [
                int(id)
                for id in form.reports_without_ticket_omit_user_ids.data
            ]
            config_obj.freelancers = form.freelancers.data
            config_obj.hours_ticket_user_id = form.hours_ticket_user_id.data if form.hours_ticket_user_id.data else None
            config_obj.monthly_late_limit = form.monthly_late_limit.data
            config_obj.monthly_incorrect_time_record_limit = form.monthly_incorrect_time_record_limit.data

            self.session.add(config_obj)

            config_obj.invalidate_office_ip()
            LOG(u"Config object saved")
            self.flash(self._(u'Application Config saved'), klass='success')
            return HTTPFound(
                location=self.request.url_for('/config/view', subpage=subpage))
        return dict(
            form=form,
            subpage=subpage,
        )
Exemple #32
0
    def dispatch(self):
        subpage = self.request.GET.get('subpage', 'general')
        config_obj = ApplicationConfig.get_current_config(allow_empty=True)

        if config_obj is not None:
            LOG(u"Found config object from %s" % (config_obj.date, ))
            form = ConfigForm(self.request.POST, obj=config_obj)
        else:
            LOG(u"Config object not found")
            form = ConfigForm(self.request.POST)
        if self.request.method == 'POST' and form.validate():
            if config_obj is None:
                config_obj = ApplicationConfig()

            config_obj.office_ip=form.office_ip.data
            config_obj.google_user_email=form.google_user_email.data
            config_obj.google_user_password=form.google_user_password.data
            config_obj.holidays_spreadsheet=form.holidays_spreadsheet.data
            config_obj.cleaning_time_presence=form.cleaning_time_presence.data
            config_obj.hours_employee_project=form.hours_employee_project.data
            config_obj.absence_project_id=form.absence_project_id.data if form.absence_project_id.data else None
            config_obj.reports_project_ids=[int(id) for id in form.reports_project_ids.data]
            config_obj.reports_omit_user_ids=[int(id) for id in form.reports_omit_user_ids.data]
            config_obj.reports_without_ticket_project_ids=[int(id) for id in form.reports_without_ticket_project_ids.data]
            config_obj.reports_without_ticket_omit_user_ids=[int(id) for id in form.reports_without_ticket_omit_user_ids.data]
            config_obj.freelancers=form.freelancers.data
            config_obj.hours_ticket_user_id=form.hours_ticket_user_id.data if form.hours_ticket_user_id.data else None
            config_obj.monthly_late_limit = form.monthly_late_limit.data
            config_obj.monthly_incorrect_time_record_limit = form.monthly_incorrect_time_record_limit.data

            self.session.add(config_obj)

            config_obj.invalidate_office_ip()
            LOG(u"Config object saved")
            self.flash(self._(u'Application Config saved'), klass='success')
            return HTTPFound(location=self.request.url_for('/config/view', subpage=subpage))
        return dict(
            form=form,
            subpage=subpage,
        )
Exemple #33
0
 def _fetch_bugs(self, sprint):
     config_obj = ApplicationConfig.get_current_config()
     user = User.query.get(config_obj.hours_ticket_user_id)
     bugs = Bugs(self.request, user).get_sprint(sprint)
     return bugs
Exemple #34
0
 def _fetch_bugs(self, sprint):
     config_obj = ApplicationConfig.get_current_config()
     user = User.query.get(config_obj.hours_ticket_user_id)
     bugs = Bugs(self.request, user).get_sprint(sprint)
     return bugs