def post_pg_control(http_context, app):
    # Control instance
    validate_parameters(http_context['post'], [
        ('action', T_CONTROL, False)
    ])
    action = http_context['post']['action']
    logger.info("PostgreSQL '%s' requested." % action)
    NotificationMgmt.push(app.config,
                          Notification(username=http_context['username'],
                                       message="PostgreSQL %s" % action))

    cmd = app.config.administration.pg_ctl % action
    cmd_args = oneline_cmd_to_array(cmd)
    (rcode, stdout, stderr) = exec_script(cmd_args)
    if rcode != 0:
        raise Exception(str(stderr))
    # Let's check if PostgreSQL is up & running after having executed
    # 'start' or 'restart' action.
    if action in ['start', 'restart']:
        # When a start/restart operation is requested, after the
        # startup/pg_ctl script has been executed then we check that
        # postgres is up & running:
        # while the PG conn. is not working then, for 10 seconds (max)
        # we'll check (connect/SELECT 1/disconnect) the connection, every
        # 0.5 second.
        retry = True
        t_start = time.time()
        while retry:
            try:
                with app.postgres.connect() as conn:
                    conn.execute('SELECT 1')
                    logger.info("Done.")
                    return dict(action=action, state='ok')
            except error:
                if (time.time() - t_start) > 10:
                    logger.info("Failed.")
                    return dict(action=action, state='ko')
            logger.info("Retrying...")
            time.sleep(0.5)

    elif action == 'stop':
        # Check the PG conn is not working anymore.
        try:
            retry = True
            t_start = time.time()
            while retry:
                with app.postgres.connect() as conn:
                    conn.execute('SELECT 1')
                time.sleep(0.5)
                if (time.time() - t_start) > 10:
                    retry = False
            logger.info("Failed.")
            return dict(action=action, state='ko')
        except error:
            logger.info("Done.")
            return dict(action=action, state='ok')

    elif action == 'reload':
        logger.info("Done.")
        return dict(action=action, state='ok')
Beispiel #2
0
def post_hba_raw(conn, config, http_context):
    new_version = False

    # Push a notification.
    try:
        NotificationMgmt.push(
            config,
            Notification(username=http_context['username'],
                         message="HBA file updated"))
    except NotificationError as e:
        logger.error(e.message)

    if 'content' not in http_context['post']:
        raise HTTPError(406, "Parameter 'content' not sent.")
    if http_context and 'new_version' in http_context['post']:
        # Check parameter 'version'
        validate_parameters(http_context['post'],
                            [('new_version', T_NEW_VERSION, False)])
        if http_context['post']['new_version'] is True:
            new_version = True

    hba_file = get_setting(conn, 'hba_file')
    return HBAManager.save_file_content(hba_file,
                                        http_context['post']['content'],
                                        new_version)
Beispiel #3
0
def post_hba(conn, config, http_context):
    new_version = False
    set_logger_name("settings")
    logger = get_logger(config)

    # Push a notification.
    try:
        NotificationMgmt.push(
            config,
            Notification(username=http_context['username'],
                         message="HBA file updated"))
    except NotificationError as e:
        logger.error(e.message)

    if 'entries' not in http_context['post']:
        raise HTTPError(406, "Parameter 'entries' not sent.")

    if http_context and 'new_version' in http_context['post']:
        # Check parameter 'version'
        validate_parameters(http_context['post'],
                            [('new_version', T_NEW_VERSION, False)])
        if http_context['post']['new_version'] is True:
            new_version = True

    hba_file = get_setting(conn, 'hba_file')
    hba_entries = []
    logger.debug(http_context['post']['entries'])
    for entry in http_context['post']['entries']:
        if 'comment' in entry and len(entry['connection']) == 0:
            new_hba_entry = HBAComment()
            new_hba_entry.comment = entry['comment']
        else:
            new_hba_entry = HBAEntry()
            try:
                new_hba_entry.connection = entry[
                    'connection'] if 'connection' in entry else ''
                new_hba_entry.database = entry[
                    'database'] if 'database' in entry else ''
                new_hba_entry.user = entry['user'] if 'user' in entry else ''
                new_hba_entry.address = entry[
                    'address'] if 'address' in entry else ''
                new_hba_entry.auth_method = entry[
                    'auth_method'] if 'auth_method' in entry else ''
                new_hba_entry.auth_options = entry[
                    'auth_options'] if 'auth_options' in entry else ''
            except Exception as e:
                logger.error(e.message)
                raise HTTPError(406, "Invalid HBA entry.")
            new_hba_entry.lazy_check()
        hba_entries.append(new_hba_entry)
    return HBAManager.save_entries(hba_file, hba_entries, new_version)
Beispiel #4
0
def logout(http_context, app, sessions):
    headers = http_context['headers']
    logger.info("Removing session: %s" % (headers['X-Session']))
    try:
        NotificationMgmt.push(app.config,
                              Notification(username=http_context['username'],
                                           message="Logout"))
    except NotificationError as e:
        logger.exception(e)

    try:
        sessions.delete(headers['X-Session'].encode('utf-8'))
        return {'logout': True}
    except (SharedItem_exists, SharedItem_no_free_slot_left) as e:
        logger.exception(e)
        raise HTTPError(500, "Internal error.")
Beispiel #5
0
    def purge_expired(self, ttl, logger, config):
        """
        Remove old Session when the Session last update time + TTL is prior to
         current timestamp.
        """
        for i in range(0, self.size):
            if len(self.sessions[i].sessionid) == T_SESSIONID_SIZE and \
                (self.sessions[i].time + ttl) < time.time():
                logger.info("Session with sessionid=%s expired." %
                                (self.sessions[i].sessionid))
                try:
                    NotificationMgmt.push(config, Notification(
                                        username = self.sessions[i].username,
                                        message = "Session expired"))
                except NotificationError as e:
                    logger.error(e.message)

                self.sessions[i] = Session()
Beispiel #6
0
def post_activity_kill(conn, config, http_context):
    validate_parameters(http_context['post'], [('pids', T_PID, True)])
    ret = {'backends': []}
    for pid in http_context['post']['pids']:
        conn.execute("SELECT pg_terminate_backend(%s) AS killed" % (pid))
        # Push a notification.
        try:
            NotificationMgmt.push(
                config,
                Notification(username=http_context['username'],
                             message="Backend %s terminated" % (pid)))
        except (NotificationError, Exception) as e:
            pass

        ret['backends'].append({
            'pid': pid,
            'killed': list(conn.get_rows())[0]['killed']
        })
    return ret
Beispiel #7
0
def notifications(http_context, app, sessions):
    logger.info("Get notifications.")
    try:
        notifications = NotificationMgmt.get_last_n(app.config, -1)
        logger.info("Done.")
        return list(notifications)
    except (NotificationError, Exception) as e:
        logger.exception(e)
        logger.info("Failed.")
        raise HTTPError(500, "Internal error.")
Beispiel #8
0
def logout(http_context, config=None, sessions=None):
    headers = http_context['headers']
    logger.info("Removing session: %s" % (headers['X-Session']))
    try:
        username = check_sessionid(headers, sessions)
    except HTTPError as e:
        logger.exception(e.message)
        logger.info("Invalid session.")
        raise e

    try:
        NotificationMgmt.push(
            config, Notification(username=username, message="Logout"))
    except NotificationError as e:
        logger.exception(e.message)

    try:
        sessions.delete(headers['X-Session'].encode('utf-8'))
    except (SharedItem_exists, SharedItem_no_free_slot_left) as e:
        logger.exception(e.message)
        raise HTTPError(500, "Internal error.")
    return {'logout': True}
Beispiel #9
0
def delete_hba_version(conn, config, http_context):
    version = None

    if http_context and 'version' in http_context['query']:
        # Check parameter 'version'
        validate_parameters(http_context['query'],
                            [('version', T_FILE_VERSION, True)])
        version = http_context['query']['version'][0]
    if version is None:
        raise HTTPError(406, "HBA version number must be specified.")

    hba_file = get_setting(conn, 'hba_file')
    # Push a notification.
    try:
        NotificationMgmt.push(
            config,
            Notification(username=http_context['username'],
                         message="HBA file version '%s' removed." % (version)))
    except NotificationError as e:
        logger.error(e.message)

    return HBAManager.remove_version(hba_file, version)
Beispiel #10
0
def login(http_context, app, sessions):
    post = http_context['post']
    # Add an unconditional sleeping time to reduce brute-force risks
    time.sleep(1)

    logger.info("Authenticating user: %s" % (post['username']))
    try:
        validate_parameters(post,
                            [('username', T_USERNAME, False),
                             ('password', T_PASSWORD, False)])
        auth_user(app.config.temboard['users'],
                  post['username'], post['password'])
    except HTTPError as e:
        logger.info("Authentication failed.")
        raise e
    try:
        session = sessions.get_by_username(post['username'])
        if not session:
            sessionid = gen_sessionid(post['username'])
            session = Session(sessionid.encode('utf-8'),
                              time.time(),
                              post['username'].encode('utf-8'))
            sessions.add(session)
        else:
            sessionid = session.sessionid
            session.time = time.time()
            sessions.update(session)
        try:
            NotificationMgmt.push(app.config,
                                  Notification(username=post['username'],
                                               message="Login"))
        except NotificationError as e:
            logger.exception(e)

        return {'session': sessionid}
    except (SharedItem_exists, SharedItem_no_free_slot_left) as e:
        logger.exception(e)
        raise HTTPError(500, "Internal error.")
Beispiel #11
0
def post_activity_kill(conn, config, http_context):
    """
    Kill (using pg_terminate_backend()) processes based on a given backend PID
    list.
    """
    validate_parameters(http_context['post'], [('pids', T_PID, True)])
    ret = {'backends': []}
    for pid in http_context['post']['pids']:
        killed = conn.query_scalar(
            "SELECT pg_terminate_backend(%s) AS killed" % (pid))
        # Push a notification.
        try:
            NotificationMgmt.push(
                config,
                Notification(username=http_context['username'],
                             message="Backend %s terminated" % (pid)))
        except (NotificationError, Exception):
            pass

        ret['backends'].append({
            'pid': pid,
            'killed': killed,
        })
    return ret
Beispiel #12
0
def notifications(http_context, config=None, sessions=None):
    headers = http_context['headers']
    logger.info("Get notifications.")
    try:
        check_sessionid(headers, sessions)
    except HTTPError as e:
        logger.exception(e.message)
        logger.info("Invalid session.")
        raise e

    try:
        notifications = NotificationMgmt.get_last_n(config, -1)
        logger.info("Done.")
        return list(notifications)
    except (NotificationError, Exception) as e:
        logger.exception(e.message)
        logger.info("Failed.")
        raise HTTPError(500, "Internal error.")
Beispiel #13
0
def post_settings(conn, config, http_context):
    set_logger_name("settings")
    logger = get_logger(config)

    if http_context and 'filter' in http_context['query']:
        # Check 'filter' parameters.
        validate_parameters(http_context['query'],
                            [('filter', T_PGSETTINGS_FILTER, True)])
    pg_config_categories = get_settings(conn, config, None)
    if 'settings' not in http_context['post']:
        raise HTTPError(406, "Parameter 'settings' not sent.")
    settings = http_context['post']['settings']
    ret = {'settings': []}
    do_not_check_names = ['unix_socket_permissions', 'log_file_mode']
    logger.debug(settings)
    for setting in settings:
        if 'name' not in setting \
            or 'setting' not in setting:
            raise HTTPError(406, "setting item malformed.")
        checked = False
        try:
            for pg_config_category in pg_config_categories:
                for pg_config_item in pg_config_category['rows']:
                    if pg_config_item['name'] == setting['name']:
                        if pg_config_item['name'] in do_not_check_names:
                            checked = True
                            raise Exception()
                        if pg_config_item['vartype'] == u'integer':
                            # Integers handling.
                            if pg_config_item['min_val'] and pg_config_item['unit'] and \
                                (int(human_to_number(setting['setting'], pg_config_item['unit'])) < int(pg_config_item['min_val'])):
                                raise HTTPError(
                                    406, "%s: Invalid setting." %
                                    (pg_config_item['name']))
                            if pg_config_item['max_val'] and pg_config_item['unit'] and \
                                (int(human_to_number(setting['setting'], pg_config_item['unit'])) > int(pg_config_item['max_val'])):
                                raise HTTPError(
                                    406, "%s: Invalid setting." %
                                    (pg_config_item['name']))
                            setting['setting'] = pg_escape(setting['setting'])
                            if ((setting['setting'].startswith("'") and setting['setting'].endswith("'")) or \
                                (setting['setting'].startswith('"') and setting['setting'].endswith('"'))):
                                setting['setting'] = setting['setting'][1:-1]
                            if setting['setting'] == '':
                                setting['setting'] = None
                            checked = True
                        if pg_config_item['vartype'] == u'real':
                            # Real handling.
                            if pg_config_item['min_val'] and \
                                (float(setting['setting']) < float(pg_config_item['min_val'])):
                                raise HTTPError(
                                    406, "%s: Invalid setting." %
                                    (pg_config_item['name']))
                            if pg_config_item['max_val'] and \
                                (float(setting['setting']) > float(pg_config_item['max_val'])):
                                raise HTTPError(
                                    406, "%s: Invalid setting." %
                                    (pg_config_item['name']))
                            setting['setting'] = float(setting['setting'])
                            checked = True
                        if pg_config_item['vartype'] == u'bool':
                            # Boolean handling.
                            if setting['setting'].lower() not in [
                                    u'on', u'off'
                            ]:
                                raise HTTPError(
                                    406, 'Invalid setting: %s.' %
                                    (setting['setting'].lower()))
                            checked = True
                        if pg_config_item['vartype'] == u'enum':
                            # Enum handling.
                            if len(pg_config_item['enumvals']) > 0:
                                enumvals = [
                                    re.sub(r"^[\"\'](.+)[\"\ ']$", r"\1",
                                           enumval) for enumval in
                                    pg_config_item['enumvals'][1:-1].split(',')
                                ]
                                if ((setting['setting'].startswith("'") and setting['setting'].endswith("'")) or \
                                    (setting['setting'].startswith('"') and setting['setting'].endswith('"'))):
                                    setting['setting'] = setting['setting'][
                                        1:-1]
                                if setting['setting'] not in enumvals:
                                    raise HTTPError(
                                        406, 'Invalid setting: %s.' %
                                        (setting['setting']))
                                checked = True
                        if pg_config_item['vartype'] == u'string':
                            # String handling.
                            # setting must be escaped.
                            setting['setting'] = pg_escape(
                                str(setting['setting']))
                            if ((setting['setting'].startswith("'") and setting['setting'].endswith("'")) or \
                                (setting['setting'].startswith('"') and setting['setting'].endswith('"'))):
                                setting['setting'] = setting['setting'][1:-1]
                            if setting['setting'] == '':
                                setting['setting'] = None
                            checked = True
                        raise Exception()
        except HTTPError as e:
            raise HTTPError(e.code, e.message['error'])
        except Exception as e:
            pass
        if not checked:
            raise HTTPError(
                406, 'Parameter %s can\'t be checked.' % (setting['name']))
        if 'force' not in setting:
            setting['force'] = 'false'
        if ((pg_config_item['vartype'] == u'integer' and setting['setting'] != pg_config_item['setting_raw']) or \
            (pg_config_item['vartype'] == u'real' and float(setting['setting']) != float(pg_config_item['setting'])) or \
            (pg_config_item['vartype'] not in [ u'integer', u'real' ] and setting['setting'] != pg_config_item['setting'])) or \
            (setting['force'] == 'true'):
            # At this point, all incoming parameters have been checked.
            if setting['setting']:
                query = "ALTER SYSTEM SET %s TO '%s'" % (setting['name'],
                                                         setting['setting'])
            else:
                query = "ALTER SYSTEM RESET %s;" % (setting['name'])

            logger.debug(query)

            # Push a notification on setting change.
            try:
                NotificationMgmt.push(
                    config,
                    Notification(
                        username=http_context['username'],
                        message="Setting '%s' changed: '%s' -> '%s'" %
                        (pg_config_item['name'], pg_config_item['setting_raw'],
                         setting['setting'])))
            except NotificationError as e:
                logger.error(e.message)

            try:
                conn.execute(query)
            except error as e:
                raise HTTPError(408, "%s: %s" % (setting['name'], e.message))
            ret['settings'].append({
                'name':
                pg_config_item['name'],
                'setting':
                setting['setting'],
                'previous_setting':
                pg_config_item['setting_raw'],
                'restart':
                True if pg_config_item['context']
                in ['internal', 'postmaster'] else False
            })
    # Reload PG configuration.
    conn.execute("SELECT pg_reload_conf()")
    # Push a notification.
    try:
        NotificationMgmt.push(
            config,
            Notification(username=http_context['username'],
                         message="PostgreSQL reload"))
    except NotificationError as e:
        logger.error(e.message)

    return ret
Beispiel #14
0
def post_pg_control(http_context, queue_in = None, config = None, sessions = None, commands = None):
    # NOTE: in this case we don't want to use api functions wrapper, it leads
    # to "Broken pipe" error with debian init.d on start/restart. This is
    # probably due to getattr() call.
    set_logger_name("administration")
    # Get a new logger.
    logger = get_logger(config)
    check_sessionid(http_context['headers'], sessions)
    post = http_context['post']
    # Check POST parameters.
    validate_parameters(post, [
        ('action', T_CONTROL, False)
    ])

    try:
        session = sessions.get_by_sessionid(http_context['headers']['X-Session'].encode('utf-8'))
        NotificationMgmt.push(config, Notification(
                                        username = session.username,
                                        message = "PostgreSQL %s" % (post['action'])))
    except NotificationError as e:
        logger.error(e.message)

    cmd_args = oneline_cmd_to_array(config.plugins['administration']['pg_ctl'] % (post['action']))
    (rcode, stdout, stderr) = exec_script(cmd_args)
    if rcode != 0:
        raise HTTPError(408, str(stderr))
    # Let's check if postgresql is up & running on 'start' or 'restart' action.
    if post['action'] in ['start', 'restart']:
        conn = connector(
            host = config.postgresql['host'],
            port = config.postgresql['port'],
            user = config.postgresql['user'],
            password = config.postgresql['password'],
            database = config.postgresql['dbname']
        )
        # When a start/restart operation is requested, after the startup/pg_ctl
        # script is executed we check that postgres is up & running: while the
        # PG connection is not working, during 10 seconds (max) we'll check
        # (connect/SELECT 1/disconnect) the connection, every 0.5 second.
        retry = True
        t_start = time.time()
        while retry:
            try:
                conn.connect()
                conn.execute('SELECT 1')
                conn.close()
                return {'action': post['action'], 'state': 'ok'}
            except error as e:
                if (time.time() - t_start) > 10:
                    try:
                        conn.close()
                    except error as e:
                        pass
                    except Exception:
                        pass
                    return {'action': post['action'], 'state': 'ko'}
            time.sleep(0.5)

    elif post['action'] == 'stop':
        conn = connector(
            host = config.postgresql['host'],
            port = config.postgresql['port'],
            user = config.postgresql['user'],
            password = config.postgresql['password'],
            database = config.postgresql['dbname']
        )
        # Check the PG conn is not working anymore.
        try:
            retry = True
            t_start = time.time()
            while retry:
                conn.connect()
                conn.execute('SELECT 1')
                conn.close()
                time.sleep(0.5)
                if (time.time() - t_start) > 10:
                    retry = False
            return {'action': post['action'], 'state': 'ko'}
        except error as e:
            return {'action': post['action'], 'state': 'ok'}
    return {'action': post['action'], 'state': 'ok'}
Beispiel #15
0
 def get_notifications(self, config):
     return list(NotificationMgmt.get_last_n(config, 15))
Beispiel #16
0
def post_pg_control(http_context, config=None, sessions=None):
    # NOTE: in this case we don't want to use api functions wrapper, it leads
    # to "Broken pipe" error with debian init.d script on start/restart.
    # This is probably due to getattr() call.
    post = http_context['post']

    try:
        check_sessionid(http_context['headers'], sessions)
        # Check POST parameters.
        validate_parameters(post, [('action', T_CONTROL, False)])
        session = sessions.get_by_sessionid(
            http_context['headers']['X-Session'].encode('utf-8'))
    except (Exception, HTTPError) as e:
        logger.exception(str(e))
        logger.debug(http_context)
        if isinstance(e, HTTPError):
            raise e
        else:
            raise HTTPError(500, "Internal error.")

    try:
        NotificationMgmt.push(
            config,
            Notification(username=session.username,
                         message="PostgreSQL %s" % post['action']))
    except (NotificationError, Exception) as e:
        logger.exception(str(e))

    try:
        logger.info("PostgreSQL '%s' requested." % (post['action']))
        cmd_args = oneline_cmd_to_array(
            config.plugins['administration']['pg_ctl'] % (post['action']))
        (rcode, stdout, stderr) = exec_script(cmd_args)
        if rcode != 0:
            raise Exception(str(stderr))
        # Let's check if PostgreSQL is up & running after having executed
        # 'start' or 'restart' action.
        if post['action'] in ['start', 'restart']:
            conn = connector(host=config.postgresql['host'],
                             port=config.postgresql['port'],
                             user=config.postgresql['user'],
                             password=config.postgresql['password'],
                             database=config.postgresql['dbname'])
            # When a start/restart operation is requested, after the
            # startup/pg_ctl script has been executed then we check that
            # postgres is up & running:
            # while the PG conn. is not working then, for 10 seconds (max)
            # we'll check (connect/SELECT 1/disconnect) the connection, every
            # 0.5 second.
            retry = True
            t_start = time.time()
            while retry:
                try:
                    conn.connect()
                    conn.execute('SELECT 1')
                    conn.close()
                    logger.info("Done.")
                    return {'action': post['action'], 'state': 'ok'}
                except error:
                    if (time.time() - t_start) > 10:
                        try:
                            conn.close()
                        except error:
                            pass
                        except Exception:
                            pass
                        logger.info("Failed.")
                        return {'action': post['action'], 'state': 'ko'}
                time.sleep(0.5)

        elif post['action'] == 'stop':
            conn = connector(host=config.postgresql['host'],
                             port=config.postgresql['port'],
                             user=config.postgresql['user'],
                             password=config.postgresql['password'],
                             database=config.postgresql['dbname'])
            # Check the PG conn is not working anymore.
            try:
                retry = True
                t_start = time.time()
                while retry:
                    conn.connect()
                    conn.execute('SELECT 1')
                    conn.close()
                    time.sleep(0.5)
                    if (time.time() - t_start) > 10:
                        retry = False
                logger.info("Failed.")
                return {'action': post['action'], 'state': 'ko'}
            except error:
                logger.info("Done.")
                return {'action': post['action'], 'state': 'ok'}
        logger.info("Done.")
        return {'action': post['action'], 'state': 'ok'}
    except (Exception, error, HTTPError) as e:
        logger.exception(str(e))
        logger.info("Failed")
        if isinstance(e, HTTPError):
            raise e
        else:
            raise HTTPError(500, "Internal error.")
Beispiel #17
0
def login(http_context,
          queue_in=None,
          config=None,
          sessions=None,
          commands=None):
    """
    @api {get} /login User login
    @apiVersion 0.0.1
    @apiName UserLogin
    @apiGroup User

    @apiParam {String} username Username.
    @apiParam {String} password Password.

    @apiSuccess {String} sessions Session ID.

    @apiExample {curl} Example usage:
        curl -k -X POST -H "Content-Type: application/json" -d '{"username": "******", "password": "******"}' \
            https://localhost:2345/login

    @apiSuccessExample Success-Reponse:
        HTTP/1.0 200 OK
        Server: temboard-agent/0.0.1 Python/2.7.8
        Date: Wed, 22 Apr 2015 12:19:48 GMT
        Content-type: application/json

        {"session": "fa452548403ac53f2158a65f5eb6db9723d2b07238dd83f5b6d9ca52ce817b63"}

    @apiError (500 error) error Internal error.
    @apiError (404 error) error Invalid username or password.
    @apiError (406 error) error Username or password malformed or missing.

    @apiErrorExample 404 error example
        HTTP/1.0 404 Not Found
        Server: temboard-agent/0.0.1 Python/2.7.8
        Date: Wed, 22 Apr 2015 12:20:33 GMT
        Content-type: application/json

        {"error": "Invalid username/password."}

    @apiErrorExample 406 error example
        HTTP/1.0 406 Not Acceptable
        Server: temboard-agent/0.0.1 Python/2.7.8
        Date: Wed, 22 Apr 2015 12:21:01 GMT
        Content-type: application/json

        {"error": "Parameter 'password' is malformed."}
    """
    post = http_context['post']
    set_logger_name("api")
    logger = get_logger(config)
    # Add an unconditional sleeping time to reduce brute-force risks
    time.sleep(1)

    logger.info("Authenticating user: %s" % (post['username']))
    try:
        validate_parameters(post, [('username', T_USERNAME, False),
                                   ('password', T_PASSWORD, False)])
        auth_user(config.temboard['users'], post['username'], post['password'])
    except HTTPError as e:
        logger.traceback(get_tb())
        logger.error(e.message)
        logger.info("Authentication failed.")
        raise e
    try:
        session = sessions.get_by_username(post['username'])
        if not session:
            sessionid = gen_sessionid(post['username'])
            session = Session(sessionid.encode('utf-8'), time.time(),
                              post['username'].encode('utf-8'))
            sessions.add(session)
        else:
            sessionid = session.sessionid
            session.time = time.time()
            sessions.update(session)
        try:
            NotificationMgmt.push(
                config, Notification(username=post['username'],
                                     message="Login"))
        except NotificationError as e:
            logger.traceback(get_tb())
            logger.error(e.message)

    except (SharedItem_exists, SharedItem_no_free_slot_left) as e:
        logger.traceback(get_tb())
        logger.error(e.message)
        raise HTTPError(500, "Internal error.")
    return {'session': sessionid}
Beispiel #18
0
def notifications(http_context,
                  queue_in=None,
                  config=None,
                  sessions=None,
                  commands=None):
    """
    @api {get} /notifications Get all notifications.
    @apiVersion 0.0.1
    @apiName Notifications
    @apiGroup User

    @apiHeader {String} X-Session Session ID.

    @apiSuccess {Object[]} notifications List of notifications.
    @apiSuccess {String}   notifications.date Notification datetime.
    @apiSuccess {String}   notifications.username Username.
    @apiSuccess {String}   notifications.message Message.

    @apiExample {curl} Example usage:
        curl -k -H "X-Session: fa452548403ac53f2158a65f5eb6db9723d2b07238dd83f5b6d9ca52ce817b63" https://localhost:2345/notifications

    @apiSuccessExample Success-Reponse:
        HTTP/1.0 200 OK
        Server: temboard-agent/0.0.1 Python/2.7.8
        Date: Wed, 22 Apr 2015 12:33:19 GMT
        Content-type: application/json

        [
            {"date": "2016-04-11T16:12:38", "username": "******", "message": "Login"},
            {"date": "2016-04-11T16:02:03", "username": "******", "message": "Login"},
            {"date": "2016-04-11T15:51:15", "username": "******", "message": "HBA file version '2016-04-11T15:32:53' removed."},
            {"date": "2016-04-11T15:51:10", "username": "******", "message": "HBA file version '2016-04-11T15:47:26' removed."},
            {"date": "2016-04-11T15:51:04", "username": "******", "message": "HBA file version '2016-04-11T15:48:50' removed."},
            {"date": "2016-04-11T15:50:57", "username": "******", "message": "PostgreSQL reload"},
            {"date": "2016-04-11T15:50:57", "username": "******", "message": "HBA file updated"},
            {"date": "2016-04-11T15:48:50", "username": "******", "message": "PostgreSQL reload"}
        ]

    @apiError (500 error) error Internal error.
    @apiError (401 error) error Invalid session ID.
    @apiError (406 error) error Session ID malformed.

    @apiErrorExample 401 error example
        HTTP/1.0 401 Unauthorized
        Server: temboard-agent/0.0.1 Python/2.7.8
        Date: Wed, 22 Apr 2015 12:36:33 GMT
        Content-type: application/json

        {"error": "Invalid session."}

    @apiErrorExample 406 error example
        HTTP/1.0 406 Not Acceptable
        Server: temboard-agent/0.0.1 Python/2.7.8
        Date: Wed, 22 Apr 2015 12:37:23 GMT
        Content-type: application/json

        {"error": "Parameter 'X-Session' is malformed."}
    """
    headers = http_context['headers']
    set_logger_name("api")
    logger = get_logger(config)
    logger.info("Get notifications.")
    try:
        username = check_sessionid(headers, sessions)
    except HTTPError as e:
        logger.traceback(get_tb())
        logger.error(e.message)
        logger.info("Invalid session.")
        raise e

    try:
        notifications = NotificationMgmt.get_last_n(config, -1)
        logger.info("Done.")
        return list(notifications)
    except (NotificationError, Exception) as e:
        logger.traceback(get_tb())
        logger.error(e.message)
        logger.info("Failed.")
        raise HTTPError(500, "Internal error.")
Beispiel #19
0
def logout(http_context,
           queue_in=None,
           config=None,
           sessions=None,
           commands=None):
    """
    @api {get} /logout User logout
    @apiVersion 0.0.1
    @apiName UserLogout
    @apiGroup User

    @apiHeader {String} X-Session Session ID.

    @apiSuccess {Bool} logout True if logout succeeds.

    @apiExample {curl} Example usage:
        curl -k -H "X-Session: fa452548403ac53f2158a65f5eb6db9723d2b07238dd83f5b6d9ca52ce817b63" https://localhost:2345/logout

    @apiSuccessExample Success-Reponse:
        HTTP/1.0 200 OK
        Server: temboard-agent/0.0.1 Python/2.7.8
        Date: Wed, 22 Apr 2015 12:33:19 GMT
        Content-type: application/json

        {"logout": true}

    @apiError (500 error) error Internal error.
    @apiError (401 error) error Invalid session ID.
    @apiError (406 error) error Session ID malformed.

    @apiErrorExample 401 error example
        HTTP/1.0 401 Unauthorized
        Server: temboard-agent/0.0.1 Python/2.7.8
        Date: Wed, 22 Apr 2015 12:36:33 GMT
        Content-type: application/json

        {"error": "Invalid session."}

    @apiErrorExample 406 error example
        HTTP/1.0 406 Not Acceptable
        Server: temboard-agent/0.0.1 Python/2.7.8
        Date: Wed, 22 Apr 2015 12:37:23 GMT
        Content-type: application/json

        {"error": "Parameter 'X-Session' is malformed."}
    """
    headers = http_context['headers']
    set_logger_name("api")
    logger = get_logger(config)
    logger.info("Removing session: %s" % (headers['X-Session']))
    try:
        username = check_sessionid(headers, sessions)
    except HTTPError as e:
        logger.traceback(get_tb())
        logger.error(e.message)
        logger.info("Invalid session.")
        raise e

    try:
        NotificationMgmt.push(
            config, Notification(username=username, message="Logout"))
    except NotificationError as e:
        logger.traceback(get_tb())
        logger.error(e.message)

    try:
        sessions.delete(headers['X-Session'].encode('utf-8'))
    except (SharedItem_exists, SharedItem_no_free_slot_left) as e:
        logger.traceback(get_tb())
        logger.error(e.message)
        raise HTTPError(500, "Internal error.")
    return {'logout': True}