def send(self, message):
     if time.time() - self.last_auth > self.refresh:
         self.authenticate()
     connection = db.connect()
     cursor = connection.cursor()
     try:
         cursor.execute(
             '''SELECT `destination` FROM `user_contact`
                           WHERE `user_id` = (SELECT `id` FROM `user` WHERE `name` = %s)
                           AND `mode_id` = (SELECT `id` FROM `contact_mode` WHERE `name` = 'rocketchat')''',
             message['user'])
         if cursor.rowcount == 0:
             raise ValueError('Rocketchat username not found for %s' %
                              message['user'])
         target = cursor.fetchone()[0]
     finally:
         cursor.close()
         connection.close()
     re = requests.post(self.api_host + '/api/v1/chat.postMessage',
                        json={
                            'channel':
                            '@%s' % target,
                            'text':
                            ' -- '.join(
                                [message['subject'], message['body']])
                        },
                        headers={
                            'X-User-Id': self.user_id,
                            'X-Auth-Token': self.token
                        })
     if re.status_code != 200 or not re.json()['success']:
         raise ValueError('Failed to contact rocketchat')
Esempio n. 2
0
def user_validator(config):
    subject = config['subject']
    body = config['body']
    sleep_time = config.get('interval', 86400)
    while 1:
        # Sleep first so bouncing notifier doesn't spam
        sleep(sleep_time)
        connection = db.connect()
        cursor = connection.cursor()
        cursor.execute('''SELECT `user`.`name`
                          FROM `event` LEFT JOIN `user_contact` ON `event`.`user_id` = `user_contact`.`user_id`
                              AND `user_contact`.`mode_id` = (SELECT `id` FROM `contact_mode` WHERE `name` = 'call')
                          JOIN `user` ON `event`.`user_id` = `user`.`id`
                          WHERE `event`.`start` > UNIX_TIMESTAMP() AND `user_contact`.`destination` IS NULL
                          GROUP BY `event`.`user_id`;''')
        for row in cursor:
            message = {
                'user': row[0],
                'mode': 'email',
                'subject': subject,
                'body': body
            }
            messengers.send_message(message)
        connection.close()
        cursor.close()
Esempio n. 3
0
def on_post(req, resp):
    login_info = uri.parse_query_string(req.context['body'])

    user = login_info.get('username')
    password = login_info.get('password')
    if user is None or password is None:
        raise HTTPBadRequest('Invalid login attempt', 'Missing user/password')

    if not auth_manager.authenticate(user, password):
        raise HTTPUnauthorized('Authentication failure',
                               'bad login credentials', '')

    connection = db.connect()
    cursor = connection.cursor(db.DictCursor)
    data = get_user_data(None, {'name': user}, dbinfo=(connection, cursor))
    if not data:
        cursor.close()
        connection.close()
        raise HTTPNotFound()

    session = req.env['beaker.session']
    session['user'] = user
    session.save()
    csrf_token = '%x' % SystemRandom().getrandbits(128)
    cursor.execute(
        'INSERT INTO `session` (`id`, `csrf_token`) VALUES (%s, %s)',
        (req.env['beaker.session']['_id'], csrf_token))
    connection.commit()
    cursor.close()
    connection.close()

    # TODO: purge out of date csrf token
    data[0]['csrf_token'] = csrf_token
    resp.body = dumps(data[0])
Esempio n. 4
0
def main():
    config = utils.read_config(sys.argv[1])
    db.init(config['db'])

    cycle_time = config.get('scheduler_cycle_time', 3600)

    while 1:
        connection = db.connect()
        db_cursor = connection.cursor(db.DictCursor)

        start = time.time()
        # Iterate through all teams
        db_cursor.execute('SELECT id, name, scheduling_timezone FROM team WHERE active = TRUE')
        teams = db_cursor.fetchall()
        for team in teams:
            team_id = team['id']
            # Get rosters for team
            db_cursor.execute('SELECT `id`, `name` FROM `roster` WHERE `team_id` = %s', team_id)
            rosters = db_cursor.fetchall()
            if db_cursor.rowcount == 0:
                continue
            logger.info('scheduling for team: %s', team['name'])
            events = []
            for roster in rosters:
                roster_id = roster['id']
                # Get schedules for each roster
                schedules = get_schedules({'team_id': team_id, 'roster_id': roster_id})
                for schedule in schedules:
                    if schedule['auto_populate_threshold'] <= 0:
                        continue
                    logger.info('\t\tschedule: %s', str(schedule['id']))
                    schedule['timezone'] = team['scheduling_timezone']
                    # Calculate events for schedule
                    future_events, last_epoch = calculate_future_events(schedule, db_cursor)
                    role_id = get_role_id(schedule['role'], db_cursor)
                    for epoch in future_events:
                        # Add (start_time, schedule_id, role_id, roster_id, epoch_events) to events
                        events.append((min([ev['start'] for ev in epoch]), schedule['id'], role_id, roster_id, epoch))
                    set_last_epoch(schedule['id'], last_epoch, db_cursor)
            # Create events in the db, associating a user to them
            # Iterate through events in order of start time to properly assign users
            for event_info in sorted(events, key=lambda x: x[0]):
                _, schedule_id, role_id, roster_id, epoch = event_info
                user_id = find_least_active_available_user_id(team_id, role_id, roster_id, epoch, db_cursor)
                if not user_id:
                    logger.info('Failed to find available user')
                    continue
                logger.info('Found user: %s', user_id)
                create_events(team_id, schedule_id, user_id, epoch, role_id, db_cursor)
            connection.commit()
        # Sleep until next time
        sleep_time = cycle_time - (time.time() - start)
        if sleep_time > 0:
            logger.info('Sleeping for %s seconds' % sleep_time)
            time.sleep(cycle_time - (time.time() - start))
        else:
            logger.info('Schedule loop took %s seconds, skipping sleep' % (time.time() - start))

        db_cursor.close()
        connection.close()
Esempio n. 5
0
def mark_message_as_unsent(msg_info):
    connection = db.connect()
    cursor = connection.cursor()
    cursor.execute(
        'UPDATE `notification_queue` SET `active` = 0, `sent` = 0 WHERE `id` = %s',
        msg_info['id'])
    connection.commit()
    connection.close()
    cursor.close()
Esempio n. 6
0
 def link(self, ids):
     connection = db.connect()
     cursor = connection.cursor()
     link_id = uuid4().hex
     cursor.execute('UPDATE `event` SET `link_id` = %s WHERE `id` IN %s', (link_id, ids))
     connection.commit()
     cursor.close()
     connection.close()
     return link_id
Esempio n. 7
0
    def ldap_auth(self, username, password):
        if self.cert_path:
            ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, self.cert_path)

        connection = ldap.initialize(self.ldap_url)
        connection.set_option(ldap.OPT_REFERRALS, 0)
        attrs = ['dn'] + self.attrs.values()
        ldap_contacts = {}

        if not password:
            return False

        auth_user = username + self.user_suffix
        try:
            if self.bind_user:
                # use search filter to find DN of username
                connection.simple_bind_s(self.bind_user, self.bind_password)
                sfilter = self.search_filter % username
                result = connection.search_s(self.base_dn, ldap.SCOPE_SUBTREE,
                                             sfilter, attrs)
                if len(result) < 1:
                    return False
                auth_user = result[0][0]
                ldap_attrs = result[0][1]
                for key, val in self.attrs.iteritems():
                    if ldap_attrs.get(val):
                        if type(ldap_attrs.get(val)) == list:
                            ldap_contacts[key] = ldap_attrs.get(val)[0]
                        else:
                            ldap_contacts[key] = ldap_attrs.get(val)
                    else:
                        ldap_contacts[key] = val

            connection.simple_bind_s(auth_user, password)

        except ldap.INVALID_CREDENTIALS:
            return False
        except (ldap.SERVER_DOWN, ldap.INVALID_DN_SYNTAX) as err:
            logger.warn("%s", err)
            return None

        if self.import_user:
            connection = db.connect()
            cursor = connection.cursor(db.DictCursor)
            if user_exists(username, cursor):
                logger.info("user %s already exists, updating from ldap",
                            username)
                update_user(username, ldap_contacts, cursor)
            else:
                logger.info("user %s does not exists. importing.", username)
                import_user(username, ldap_contacts, cursor)
            connection.commit()
            cursor.close()
            connection.close()

        return True
Esempio n. 8
0
def get_audit_log(start, end):
    connection = db.connect()
    cursor = connection.cursor()
    cursor.execute(
        'SELECT action_name FROM audit WHERE timestamp BETWEEN %s AND %s',
        (int(start), int(end) + 1))
    ret = {row[0] for row in cursor}
    cursor.close()
    connection.close()
    return ret
Esempio n. 9
0
    def tearDown(self):
        connection = db.connect()
        cursor = connection.cursor()

        cursor.execute("DELETE FROM `team` WHERE `name` = %s", self.team_name)
        cursor.execute("DELETE FROM `user` WHERE `name` IN %s",
                       ([self.user_name, self.admin_name], ))

        connection.commit()
        cursor.close()
        connection.close()
Esempio n. 10
0
def get_notifications(usernames, type_name):
    connection = db.connect()
    cursor = connection.cursor(db.DictCursor)
    cursor.execute('''SELECT user.name AS user
                      FROM notification_queue JOIN user ON user_id = user.id
                        JOIN notification_type ON notification_queue.type_id = notification_type.id
                      WHERE user_id IN (SELECT id FROM user WHERE name IN %s)
                        AND notification_type.name = %s''',
                   (usernames, type_name))
    ret = cursor.fetchall()
    cursor.close()
    connection.close()
    return ret
Esempio n. 11
0
def main():
    config = utils.read_config(sys.argv[1])
    db.init(config['db'])

    cycle_time = config.get('scheduler_cycle_time', 3600)
    schedulers = {}

    while 1:
        connection = db.connect()
        db_cursor = connection.cursor(db.DictCursor)

        start = time.time()
        # Load all schedulers
        db_cursor.execute('SELECT name FROM scheduler')
        schedulers = {}
        for row in db_cursor:
            try:
                scheduler_name = row['name']
                if scheduler_name not in schedulers:
                    schedulers[scheduler_name] = load_scheduler(scheduler_name)
            except (ImportError, AttributeError):
                logger.exception('Failed to load scheduler %s, skipping',
                                 row['name'])

        # Iterate through all teams
        db_cursor.execute(
            'SELECT id, name, scheduling_timezone FROM team WHERE active = TRUE'
        )
        teams = db_cursor.fetchall()
        for team in teams:
            logger.info('scheduling for team: %s', team['name'])
            schedule_map = defaultdict(list)
            for schedule in get_schedules({'team_id': team['id']}):
                schedule_map[schedule['scheduler']['name']].append(schedule)

            for scheduler_name, schedules in schedule_map.iteritems():
                schedulers[scheduler_name].schedule(team, schedules,
                                                    (connection, db_cursor))

        # Sleep until next time
        sleep_time = cycle_time - (time.time() - start)
        if sleep_time > 0:
            logger.info('Sleeping for %s seconds' % sleep_time)
            time.sleep(cycle_time - (time.time() - start))
        else:
            logger.info('Schedule loop took %s seconds, skipping sleep' %
                        (time.time() - start))

        db_cursor.close()
        connection.close()
Esempio n. 12
0
def poll():
    query = '''SELECT `user`.`name` AS `user`, `contact_mode`.`name` AS `mode`, `notification_queue`.`send_time`,
                      `user`.`time_zone`,`notification_type`.`subject`, `notification_queue`.`context`,
                      `notification_type`.`body`, `notification_queue`.`id`
               FROM `notification_queue` JOIN `user` ON `notification_queue`.`user_id` = `user`.`id`
                   JOIN `contact_mode` ON `notification_queue`.`mode_id` = `contact_mode`.`id`
                   JOIN `notification_type` ON `notification_queue`.`type_id` = `notification_type`.`id`
               WHERE `notification_queue`.`active` = 1 AND `notification_queue`.`send_time` <= UNIX_TIMESTAMP()'''
    logger.info('[-] start send task...')

    connection = db.connect()
    cursor = connection.cursor(db.DictCursor)
    cursor.execute(query)
    for row in cursor:
        send_queue.put(row)
    cursor.close()
    connection.close()
Esempio n. 13
0
    def setUp(self):
        super(TestLogin, self).setUp()
        login.auth_manager = self.DummyAuthenticator()
        api = falcon.API(middleware=[
            ReqBodyMiddleware(),
        ])
        api.req_options.auto_parse_form_urlencoded = False
        self.api = api
        self.api.add_route('/login', login)
        self.api.add_route('/logout', logout)
        self.api.add_route('/dummy/{user}', self.UserDummy())
        self.api.add_route('/dummy2/{team}', self.TeamDummy())
        self.api = SessionMiddleware(self.api, self.session_opts)

        self.user_name = 'test_login_user'
        self.admin_name = 'test_login_admin'
        self.team_name = 'test_login_team'

        connection = db.connect()
        cursor = connection.cursor()
        # Create users
        cursor.execute("INSERT INTO `user` (`name`, `active`) VALUES (%s, 1)",
                       self.user_name)
        self.user_id = cursor.lastrowid
        cursor.execute("INSERT INTO `user` (`name`, `active`) VALUES (%s, 1)",
                       self.admin_name)
        self.admin_id = cursor.lastrowid

        # Set up team
        cursor.execute("INSERT INTO `team` (`name`) VALUES (%s)",
                       self.team_name)
        self.team_id = cursor.lastrowid
        cursor.execute("INSERT INTO `team_user` VALUES (%s, %s)",
                       (self.team_id, self.user_id))
        cursor.execute("INSERT INTO `team_user` VALUES (%s, %s)",
                       (self.team_id, self.admin_id))
        cursor.execute("INSERT INTO `team_admin` VALUES (%s, %s)",
                       (self.team_id, self.admin_id))

        connection.commit()
        cursor.close()
        connection.close()
Esempio n. 14
0
def sync_action(slack_client):
    re = slack_client.api_call("users.list")
    if not re.get('ok'):
        logger.error('Failed to fetch user list from slack')
        return

    slack_members = re['members']
    slack_users = {}

    for m in slack_members:
        if m['name'] == 'slackbot' or m['deleted']:
            continue
        user_profile = m['profile']
        slack_users[m['name']] = {
            'name': m['name'],
            'full_name': user_profile['real_name'],
            'photo_url': user_profile['image_512'],
            'email': user_profile['email'],
        }
        if 'phone' in user_profile:
            slack_users[m['name']]['phone'] = normalize_phone_number(
                user_profile['phone'])

    connection = db.connect()
    # cache mode ids
    cursor = connection.cursor()
    cursor.execute('SELECT `id`, `name` FROM `contact_mode`')
    mode_ids = {row[1]: row[0] for row in cursor}
    cursor.close()

    slack_usernames = set(slack_users.keys())
    oncall_usernames = set(fetch_oncall_usernames(connection))

    users_to_insert = slack_usernames - oncall_usernames
    users_to_delete = oncall_usernames - slack_usernames

    logger.info('users to insert: %s', users_to_insert)
    logger.info('users to delete: %s', users_to_delete)

    insert_users(connection, slack_users, users_to_insert, mode_ids)
    delete_users(connection, users_to_delete)
    connection.close()
Esempio n. 15
0
 def __init__(self, prefix):
     self.prefix = prefix
     self.created = set()
     self.created_ids = set()
     self.connection = db.connect()
     self.cursor = self.connection.cursor()
Esempio n. 16
0
def reminder(config):
    interval = config['polling_interval']
    default_timezone = config['default_timezone']

    connection = db.connect()
    cursor = connection.cursor()
    cursor.execute('SELECT `last_window_end` FROM `notifier_state`')
    if cursor.rowcount != 1:
        window_start = int(time.time() - interval)
        logger.warning(
            'Corrupted/missing notifier state; unable to determine last window. Guessing %s',
            window_start)
    else:
        window_start = cursor.fetchone()[0]

    cursor.close()
    connection.close()

    query = '''
        SELECT `user`.`name`, `user`.`id` AS `user_id`, `time_before`, `contact_mode`.`name` AS `mode`,
               `team`.`name` AS `team`, `event`.`start`, `event`.`id`, `role`.`name` AS `role`, `user`.`time_zone`
        FROM `user` JOIN `notification_setting` ON `notification_setting`.`user_id` = `user`.`id`
                AND `notification_setting`.`type_id` = (SELECT `id` FROM `notification_type`
                                                                  WHERE `name` = %s)
            JOIN `setting_role` ON `notification_setting`.`id` = `setting_role`.`setting_id`
            JOIN `event` ON `event`.`start` >= `time_before` + %s AND `event`.`start` < `time_before` + %s
              AND `event`.`user_id` = `user`.`id`
              AND `event`.`role_id` = `setting_role`.`role_id`
              AND `event`.`team_id` = `notification_setting`.`team_id`
            JOIN `contact_mode` ON `notification_setting`.`mode_id` = `contact_mode`.`id`
            JOIN `team` ON `event`.`team_id` = `team`.`id`
            JOIN `role` ON `event`.`role_id` = `role`.`id`
            LEFT JOIN `event` AS `e` ON `event`.`link_id` = `e`.`link_id` AND `e`.`start` < `event`.`start`
            WHERE `e`.`id` IS NULL AND `user`.`active` = 1
    '''

    while (1):
        logger.info('Reminder polling loop started')
        window_end = int(time.time())

        connection = db.connect()
        cursor = connection.cursor(db.DictCursor)

        cursor.execute(query,
                       (constants.ONCALL_REMINDER, window_start, window_end))
        notifications = cursor.fetchall()

        for row in notifications:
            context = {
                'team':
                row['team'],
                'start_time':
                timestamp_to_human_str(
                    row['start'], row['time_zone']
                    if row['time_zone'] else default_timezone),
                'time_before':
                sec_to_human_str(row['time_before']),
                'role':
                row['role']
            }
            create_reminder(row['user_id'], row['mode'],
                            row['start'] - row['time_before'], context,
                            'oncall_reminder', cursor)
            logger.info('Created reminder with context %s for %s', context,
                        row['name'])

        cursor.execute('UPDATE `notifier_state` SET `last_window_end` = %s',
                       window_end)
        connection.commit()
        logger.info('Created reminders for window [%s, %s), sleeping for %s s',
                    window_start, window_end, interval)
        window_start = window_end

        cursor.close()
        connection.close()
        sleep(interval)