예제 #1
0
def application(env, start_response):
    request = Request(env)

    try:
        with map_errors_to_http(), cursor_for_request(request) as cursor:
            cursor.execute(
                '''
                select request as json
                from www.request(%s, %s, %s::json, %s::json)
            ''', (request.method, request.path,
                  json.dumps(request.args.to_dict(flat=True)),
                  request.data.decode('utf8') if request.data else 'null'))

            row = cursor.fetchone()
            return Response(row.json, content_type="application/json")

    except HTTPException as e:
        e_resp = e.get_response()

        if (request.mimetype == 'application/json'):
            response = Response(response=json.dumps({
                "title": "Bad Request",
                "status_code": e_resp.status_code,
                "message": e.description
            }),
                                status=e_resp.status_code,
                                mimetype="application/json")

            return response

        else:
            return e
예제 #2
0
파일: data.py 프로젝트: stlee42/aquameta
def application(env, start_response):
    request = Request(env)

    try:
        with map_errors_to_http(), cursor_for_request(request) as cursor:

            # We want to maintain escaped urls as string data
            full_path = re.split('\?', env['REQUEST_URI'])[0]       # get rid of query params
            path_with_version = full_path.replace('/endpoint/', '', 1) # get rid of endpoint path
            version, path = path_with_version.split('/', 1)

            logging.info('handling request for: %s' % env['REQUEST_URI'])
            logging.debug('attempting endpoint %s, %s, %s, query %s, post %s' % (version, request.method, path, request.args, request.data))

            cursor.execute('''
                select status, message, response, mimetype
                from endpoint.request(%s, %s, %s, %s::json, %s::json)
            ''', (
                version,                                                # version - 0.1, 0.2, etc...
                request.method,                                         # verb - GET | POST | PATCH | PUT | DELETE ...
                path,                                                   # path - the relative path including leading slash but without query string
                json.dumps(request.args.to_dict(flat=False)),           # args - "url parameters", aka parsed out query string, converted to a json string
                request.get_data() if request.data else 'null'
            ))

            row = cursor.fetchone()

            if row.mimetype.startswith('image'): # There is a better way here.
                return Response(
                    response=a2b_base64(row.response),
                    content_type=row.mimetype,
                    status=row.status
                )

            # TODO?
            # How come status and message are not used here?
            return Response(
                response=row.response,
                content_type=row.mimetype,
                status=row.status
            )

    except HTTPException as e:
        e_resp = e.get_response()

        if(request.mimetype == 'application/json'):
            response = Response(
                response=json.dumps({
                    "title": "Bad Request",
                    "status_code": e_resp.status_code,
                    "message": e.description
                }),
                status=e_resp.status_code,
                mimetype="application/json"
            )

            return response

        else:
            return e
예제 #3
0
파일: auth.py 프로젝트: markdillon/aquameta
    def do_auth(self, request, start_response):
        with cursor_for_request(request) as cursor:
            cursor.execute("select auth.login(%s) as token", (request.args["hash"],))

            row = cursor.fetchone()

            if row and row.token:
                start_response("200 Found", [("Set-Cookie", "%s=%s" % (self.session_cookie, row.token))])
            else:
                start_response("401 Unauthorized", [])

            return []
예제 #4
0
파일: auth.py 프로젝트: markdillon/aquameta
    def verify_session(self, request, environ, start_response):
        environ["DB_USER"] = "******"

        if self.session_cookie in request.cookies:
            token = request.cookies["SESSION"]

            with cursor_for_request(request) as cursor:
                cursor.execute("select username from auth.session where token = %s", (token,))

                row = cursor.fetchone()
                if row:
                    environ["DB_USER"] = row.username

        return self.app(environ, start_response)
예제 #5
0
def application(env, start_response):
    request = Request(env)

    try:
        with map_errors_to_http(), cursor_for_request(request) as cursor:
            cursor.execute('select content from www.page where path = %s', (request.path,))
            row = cursor.fetchone()

            if row is None:
                raise NotFound
            else:
                return Response(row.content, content_type='text/html')

    except HTTPException as e:
        return e
예제 #6
0
    def do_auth(self, request, start_response):
        with cursor_for_request(request) as cursor:
            cursor.execute('select auth.login(%s) as token',
                           (request.args['hash'], ))

            row = cursor.fetchone()

            if row and row.token:
                start_response('200 Found',
                               [('Set-Cookie', '%s=%s' %
                                 (self.session_cookie, row.token))])
            else:
                start_response('401 Unauthorized', [])

            return []
예제 #7
0
파일: data.py 프로젝트: nijotz/aquameta
def application(env, start_response):
    request = Request(env)

    try:
        with map_errors_to_http(), cursor_for_request(request) as cursor:
            logging.info(
                'this version of the data url scheme has been deprecated. use /endpoint/new instead'
            )
            # will be
            # select status, message, response as json
            cursor.execute(
                '''
                select status, message, data2 as json
                from endpoint.request(%s, %s, %s::json, %s::json)
            ''',
                (
                    request.
                    method,  # verb - GET | POST | PATCH | PUT | DELETE ...
                    request.
                    path,  # path - the full path including leading slash but without query string
                    json.dumps(
                        request.args.to_dict(flat=True)
                    ),  # args - "url parameters", aka parsed out query string, converted to a json string
                    request.data.decode('utf8') if request.data else 'null'))

            row = cursor.fetchone()
            # return Response('Hello World!')

            # TODO?
            # How come status and message are not used here?
            return Response(row.json, content_type="application/json")

    except HTTPException as e:
        e_resp = e.get_response()

        if (request.mimetype == 'application/json'):
            response = Response(response=json.dumps({
                "title": "Bad Request",
                "status_code": e_resp.status_code,
                "message": e.description
            }),
                                status=e_resp.status_code,
                                mimetype="application/json")

            return response

        else:
            return e
예제 #8
0
    def verify_session(self, request, environ, start_response):
        environ['DB_USER'] = '******'

        if self.session_cookie in request.cookies:
            token = request.cookies['SESSION']

            with cursor_for_request(request) as cursor:
                cursor.execute(
                    "select username from auth.session where token = %s",
                    (token, ))

                row = cursor.fetchone()
                if row:
                    environ['DB_USER'] = row.username

        return self.app(environ, start_response)
예제 #9
0
    def verify_session(self, request, environ, start_response):
        environ['DB_USER'] = '******'

        if self.session_cookie in request.cookies: 
            session_id = request.cookies[self.session_cookie]

            with cursor_for_request(request) as cursor:
                try:
                    cursor.execute("select (role_id).name as role_name from endpoint.session(%s::uuid)", (session_id,))
                    row = cursor.fetchone()
                except:
                    pass
                else:
                    if row:
                        environ['DB_USER'] = row.role_name

        return self.app(environ, start_response)
예제 #10
0
파일: auth.py 프로젝트: stlee42/aquameta
    def verify_session(self, request, environ, start_response):
        environ['DB_USER'] = '******'

        if self.session_cookie in request.cookies:
            session_id = request.cookies[self.session_cookie]

            with cursor_for_request(request) as cursor:
                try:
                    cursor.execute(
                        "select (role_id).name as role_name from endpoint.session(%s::uuid)",
                        (session_id, ))
                    row = cursor.fetchone()
                except:
                    pass
                else:
                    if row:
                        environ['DB_USER'] = row.role_name

        return self.app(environ, start_response)
예제 #11
0
파일: auth.py 프로젝트: stlee42/aquameta
    def do_auth(self, request, environ, start_response):
        with cursor_for_request(request) as cursor:

            # Incomplete login attempt if email/password not POSTed
            if request.form.get('email') is None or request.form.get(
                    'password') is None:
                return []

            try:
                # Attempt login
                cursor.execute(
                    'select endpoint.login(%s, %s) as session_id',
                    (request.form.get('email'), request.form.get('password')))
                row = cursor.fetchone()

            except:
                # Exception raised from invalid email
                start_response('401 Unauthorized', [])
                redirect_response = redirect(request.full_path)
                return redirect_response(environ, start_response)

            if row and row.session_id:
                # Logged in

                # Redirect to redirectURL or /
                redirect_response = redirect(
                    request.args.get('redirectURL', '/'))
                redirect_response.set_cookie(self.session_cookie,
                                             row.session_id)
                #start_response('200 Found', [('Set-Cookie', '%s=%s' % (self.session_cookie, row.session_id))])
                return redirect_response(environ, start_response)

            else:
                # Login failed from invalid password attempt
                start_response('401 Unauthorized', [])
                redirect_response = redirect(request.full_path)
                return redirect_response(environ, start_response)
예제 #12
0
파일: data.py 프로젝트: markdillon/aquameta
def application(env, start_response):
    request = Request(env)

    try:
        with map_errors_to_http(), cursor_for_request(request) as cursor:
            cursor.execute('''
                select request as json
                from www.request(%s, %s, %s::json, %s::json)
            ''', (
                request.method,
                request.path,
                json.dumps(request.args.to_dict(flat=True)),
                request.data.decode('utf8') if request.data else 'null'
            ))

            row = cursor.fetchone()
            return Response(row.json, content_type="application/json")

    except HTTPException as e:
        e_resp = e.get_response()

        if(request.mimetype == 'application/json'):
            response = Response(
                response=json.dumps({
                    "title": "Bad Request",
                    "status_code": e_resp.status_code,
                    "message": e.description
                }),
                status=e_resp.status_code,
                mimetype="application/json"
            )

            return response

        else:
            return e
예제 #13
0
    def do_auth(self, request, environ, start_response):
        with cursor_for_request(request) as cursor:

            # Incomplete login attempt if email/password not POSTed
            if request.form.get('email') is None or request.form.get('password') is None:
                return []

            try:
                # Attempt login
                cursor.execute(
                    'select endpoint.login(%s, %s) as session_id',
                    (request.form.get('email'), request.form.get('password'))
                )
                row = cursor.fetchone()

            except:
                # Exception raised from invalid email
                start_response('401 Unauthorized', [])
                redirect_response = redirect(request.full_path)
                return redirect_response(environ, start_response)


            if row and row.session_id:
                # Logged in

                # Redirect to redirectURL or /
                redirect_response = redirect(request.args.get('redirectURL', '/'))
                redirect_response.set_cookie(self.session_cookie, row.session_id)
                #start_response('200 Found', [('Set-Cookie', '%s=%s' % (self.session_cookie, row.session_id))])
                return redirect_response(environ, start_response)

            else:
                # Login failed from invalid password attempt
                start_response('401 Unauthorized', [])
                redirect_response = redirect(request.full_path)
                return redirect_response(environ, start_response)
예제 #14
0
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            logging.info('connection established')

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] != 'ping':
                                        logging.info('command received: %s' % cmd['method'])

                                    if cmd['method'] == 'request':
                                        request_method(cmd, cursor)

                                    elif cmd['method'] == 'attach':
                                        attach_method(cmd, cursor, db_connection, env)

                                    elif cmd['method'] == 'detach':
                                        detach_method(cmd, cursor, db_connection, env)

                                except Warning as err:
                                    logging.error(str(err))
#                                    uwsgi.websocket_send(json.dumps({
#                                        "method": "log",
#                                        "args": {
#                                            "level": "warning",
#                                            "message": err.diag.message_primary
#                                        }
#                                    }))

                    elif fd == db_conn_fd:
                        handle_db_notifications(db_connection)

                    else:
                        logging.info('timeout reached') # This is never reached

                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except (OSError, IOError) as err:
                logging.info('connection closed (role: %s)' % env['DB_USER'])

        return []
예제 #15
0
def application(env, start_response):
    request = Request(env)

    try:
        with map_errors_to_http(), cursor_for_request(request) as cursor:

            # Text resource
            cursor.execute(
                '''
                select r.content, m.mimetype
                from endpoint.resource r
                    join endpoint.mimetype m on r.mimetype_id = m.id
                where path = %s
            ''', (request.path, ))
            row = cursor.fetchone()

            # Binary resource
            if row is None:
                cursor.execute(
                    '''
                    select r.content, m.mimetype
                    from endpoint.resource_binary r
                        join endpoint.mimetype m on r.mimetype_id = m.id
                    where path = %s
                ''', (request.path, ))
                row = cursor.fetchone()

            # TODO Look to see if path has ancestral index

            # File resource
            if row is None:
                cursor.execute(
                    '''
                    select f.content, m.mimetype
                    from filesystem.file f
                        left join endpoint.mimetype_extension e on e.extension = regexp_replace(f.name, '^.*\.', '')
                        left join endpoint.mimetype m on m.id = e.mimetype_id
                    where f.path = (select file_id from endpoint.resource_file where path=%s);
                ''', (request.path, ))
                row = cursor.fetchone()

            # Directory resource
            # Question: only directories where indexes = true?
            if row is None:
                cursor.execute(
                    '''
                    with dir as (
                        select directory_id as dir_id
                        from endpoint.resource_directory
                        where path=%s and indexes=true
                    )
                    select path, name, last_mod, size, endpoint.is_indexed(path) as show from filesystem.directory where parent_id=(select dir_id from dir)
                    union
                    select path, name, last_mod, size, endpoint.is_indexed(path) as show from filesystem.file where directory_id=(select dir_id from dir)
                ''', (request.path, ))
                rows = cursor.fetchall()

                if len(rows):
                    return Response(build_directory_index(request.path, rows),
                                    content_type='text/html')

            # Should this redirect to /login?
            # That would mean: Resource Not Found = Resource Not Authorized
            # Which is accurate considering RLS hides unauthorized data
            # No because auth should occur in widgets, no redirecting
            if row is None:
                # Is this returning a 404?
                raise NotFound

            return Response(row.content,
                            content_type='text/plain'
                            if row.mimetype is None else row.mimetype)

    except HTTPException as e:
        return e
예제 #16
0
파일: events.py 프로젝트: stlee42/aquameta
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            logging.info('connection established')

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] != 'ping':
                                        logging.info('command received: %s' %
                                                     cmd['method'])

                                    if cmd['method'] == 'request':
                                        request_method(cmd, cursor)

                                    elif cmd['method'] == 'attach':
                                        attach_method(cmd, cursor,
                                                      db_connection, env)

                                    elif cmd['method'] == 'detach':
                                        detach_method(cmd, cursor,
                                                      db_connection, env)

                                except Warning as err:
                                    logging.error(str(err))
#                                    uwsgi.websocket_send(json.dumps({
#                                        "method": "log",
#                                        "args": {
#                                            "level": "warning",
#                                            "message": err.diag.message_primary
#                                        }
#                                    }))

                    elif fd == db_conn_fd:
                        handle_db_notifications(db_connection)

                    else:
                        logging.info(
                            'timeout reached')  # This is never reached

                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except (OSError, IOError) as err:
                logging.info('connection closed (role: %s)' % env['DB_USER'])

        return []
예제 #17
0
def application(env, start_response):
    request = Request(env)

    try:
        with map_errors_to_http(), cursor_for_request(request) as cursor:
            rowcount = 0
            # Text resource
            cursor.execute(
                '''
                select r.content, m.mimetype
                from endpoint.resource r
                    join endpoint.mimetype m on r.mimetype_id = m.id
                where path = %s
                and active = true
            ''', (request.path, ))
            text_resources = cursor.fetchall()
            rowcount += cursor.rowcount

            # Binary resource
            cursor.execute(
                '''
                select r.content, m.mimetype
                from endpoint.resource_binary r
                    join endpoint.mimetype m on r.mimetype_id = m.id
                where path = %s
                and active = true
            ''', (request.path, ))
            binary_resources = cursor.fetchall()
            rowcount += cursor.rowcount

            # Template resource
            # check for matching route
            cursor.execute(
                '''
                select array_to_json(regexp_matches(%s, r.url_pattern)) as match from endpoint.template_route r
                ''', (request.path, ))
            routes = cursor.fetchall()
            rowcount += cursor.rowcount

            # render template if we found one ^^.  only if we don't have other rows
            template_resources = None
            if routes != None:
                cursor.execute(
                    '''
                    select
                        endpoint.template_render(
                            t.id,
                            r.args::json,
                            array_to_json( regexp_matches(%s, r.url_pattern) )
                        ) as content, 
                        m.mimetype
                    from endpoint.template_route r
                        join endpoint.template t on r.template_id = t.id
                        join endpoint.mimetype m on t.mimetype_id = m.id
                ''', (request.path, ))
                template_resources = cursor.fetchall()
#            else:
#                logging.info('HEEEEYYYYYYYY NO WE DID NOT GET a row')
#            cursor.execute('''
#                select
#                    id, regex_matches(%s, r.url_pattern),
#                    endpoint.render_template(t.id, r.args::json) as content, 'text/html' as mimetype, r.args
#                from template.template t
#                    join template.template_route r on r.template_id = t.id
#                where             ''', (request.path,))
#            template_resources = cursor.fetchall()
#            rowcount += cursor.rowcount

# detect path collisions
            if rowcount > 1:
                raise MultipleChoices

            row = None

            if len(text_resources) == 1:
                row = text_resources[0]
            if len(binary_resources) == 1:
                row = binary_resources[0]
            if len(template_resources) == 1:
                row = template_resources[0]

### Commenting out until security can be audited...
###            # File resource
###            if row is None:
###                cursor.execute('''
###                    select f.content, m.mimetype
###                    from filesystem.file f
###                        left join endpoint.mimetype_extension e on e.extension = regexp_replace(f.name, '^.*\.', '')
###                        left join endpoint.mimetype m on m.id = e.mimetype_id
###                    where f.path = (select file_id from endpoint.resource_file where path=%s and active=true)
###                ''', (request.path,))
###                row = cursor.fetchone()
###
###
###            # Directory resource
###            # Question: only directories where indexes = true?
###            if row is None:
###                cursor.execute('''
###                    with dir as (
###                        select directory_id as dir_id
###                        from endpoint.resource_directory
###                        where path=%s and indexes=true
###                    )
###                    select path, name, last_mod, size, endpoint.is_indexed(path) as show from filesystem.directory where parent_id=(select dir_id from dir)
###                    union
###                    select path, name, last_mod, size, endpoint.is_indexed(path) as show from filesystem.file where directory_id=(select dir_id from dir)
###                ''', (request.path,))
###                rows = cursor.fetchall()
###
###                if len(rows):
###                    return Response(build_directory_index(request.path, rows), content_type='text/html')
###
###            # File-in-Directory resource
###            if row is None:
###                cursor.execute('''
###                    with dir as (
###                        select directory_id as dir_id, path, char_length(path) as path_length
###                        from endpoint.resource_directory
###                        where %s like path || '%%'
###                    )
###                    select f.content, m.mimetype
###                        from filesystem.file f
###                        left join endpoint.mimetype_extension e on e.extension = regexp_replace(f.name, '^.*\.', '')
###                        left join endpoint.mimetype m on m.id = e.mimetype_id
###                        where path = (select dir_id from dir) || substring(%s from (select path_length + 1 from dir))
###                ''', (request.path,request.path))
###                row = cursor.fetchone()

# Should this redirect to /login?
# That would mean: Resource Not Found = Resource Not Authorized
# Which is accurate considering RLS hides unauthorized data
# No because auth should occur in widgets, no redirecting
            if row is None:
                # Is this returning a 404?
                raise NotFound

            return Response(row.content,
                            content_type='text/plain'
                            if row.mimetype is None else row.mimetype)

    except HTTPException as e:
        return e
예제 #18
0
파일: events.py 프로젝트: nijotz/aquameta
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            logging.info('connection established')

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] != 'ping':
                                        logging.info('command received: %s' %
                                                     cmd['method'])

                                    if cmd['method'] == 'request':

                                        logging.info(
                                            'websocket endpoint request: %s, %s, %s, %s'
                                            % (
                                                cmd['verb'],  # HTTP method               - GET, POST, PATCH, DELETE
                                                cmd['uri'],  # selector                  - '/relation/widget/dependency_js'
                                                ImmutableMultiDict(
                                                    json.loads(cmd['query'])
                                                ),  # query string arguments    - including event.session id
                                                json.dumps(
                                                    cmd['data'])  # post data
                                            ))

                                        cursor.execute(
                                            'select status, message, response, mimetype from endpoint.request2(%s, %s, %s::json, %s::json);',
                                            (
                                                cmd['verb'],  # HTTP method               - GET, POST, PATCH, DELETE
                                                cmd['uri'],  # selector                  - '/relation/widget/dependency_js'
                                                json.dumps(
                                                    ImmutableMultiDict(
                                                        json.loads(
                                                            cmd['query'])
                                                    ).to_dict(flat=False)
                                                ),  # query string arguments    - including event.session id
                                                json.dumps(
                                                    cmd['data'])  # post data
                                            ))

                                        result = cursor.fetchone()

                                        uwsgi.websocket_send('''{
                                            "method": "response",
                                            "request_id": "%s",
                                            "data": %s
                                        }''' % (cmd['request_id'],
                                                result.response))

                                    elif cmd['method'] == 'attach':
                                        session_id = cmd['session_id']
                                        if session_id is not None:
                                            cursor.execute(
                                                'select event.session_attach(%s);',
                                                (session_id, ))
                                            logging.info(
                                                'session attached: %s (role: %s)'
                                                % (session_id, env['DB_USER']))
                                            handle_db_notifications(
                                                db_connection)

                                            uwsgi.websocket_send('''{
                                                "method": "response",
                                                "request_id": "%s",
                                                "data": "true"
                                            }''' % (cmd['request_id'], ))

                                    elif cmd['method'] == 'detach':
                                        session_id = cmd['session_id']
                                        if session_id is not None:
                                            cursor.execute(
                                                'select event.session_detach(%s);',
                                                (session_id, ))
                                            logging.info(
                                                'session detached: %s (role: %s)'
                                                % (session_id, env['DB_USER']))

                                            uwsgi.websocket_send('''{
                                                "method": "response",
                                                "request_id": "%s",
                                                "data": "true"
                                            }''' % (cmd['request_id'], ))

                                    #uwsgi.websocket_send('''{
                                    #    "method": "response",
                                    #    "request_id": "%s",
                                    #    "data": %s
                                    #}''' % (cmd['request_id'], result.response))

                                except Warning as err:
                                    logging.error(str(err))
#                                    uwsgi.websocket_send(json.dumps({
#                                        "method": "log",
#                                        "args": {
#                                            "level": "warning",
#                                            "message": err.diag.message_primary
#                                        }
#                                    }))

                    elif fd == db_conn_fd:
                        handle_db_notifications(db_connection)

                    else:
                        logging.info(
                            'timeout reached')  # This is never reached

                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except (OSError, IOError) as err:
                logging.info('connection closed (role: %s)' % env['DB_USER'])

        return []
예제 #19
0
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            session_id = get_session_id(request, cursor)

            logging.info('event/table/session/row/%s:connected (role: %s)' %
                         (session_id, env['DB_USER']))

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            cursor.execute('listen "event/table/session/rows/%i"' % session_id)

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] == 'subscribe':
                                        selector, type = cmd['args'][
                                            'selector'].rsplit(':', 1)
                                        cursor.execute(
                                            "select event.subscribe_session(%s, %s, %s);",
                                            (session_id, selector, type))

                                    elif cmd['method'] == 'unsubscribe':
                                        selector, type = cmd['args'][
                                            'selector'].rsplit(':', 1)
                                        cursor.execute(
                                            "select event.unsubscribe_session(%s, %s, %s);",
                                            (session_id, selector, type))

                                except Warning as err:
                                    logging.error(str(err))
                                    uwsgi.websocket_send(
                                        json.dumps({
                                            "method": "log",
                                            "args": {
                                                "level": "warning",
                                                "message":
                                                err.diag.message_primary
                                            }
                                        }))

                    elif fd == db_conn_fd:
                        db_connection.poll()

                        if db_connection.notifies:
                            del db_connection.notifies[:]

                            cursor.execute(
                                '''
                                select *
                                from event.session_queued_events_json(%s)
                            ''', (session_id, ))

                            qe_ids = []
                            logging.info(
                                'event/table/session/row/%s:flushing_queue (role: %s)'
                                % (session_id, env['DB_USER']))

                            for row in cursor:
                                uwsgi.websocket_send(json.dumps(
                                    row.event_json))
                                logging.info(
                                    'event/table/session/row/%s:sent_json (role: %s)'
                                    % (session_id, env['DB_USER']))
                                qe_ids.append(row.queued_event_id)

                            cursor.execute(
                                '''
                                delete from event.queued_event qe
                                where qe.id = any(%s)
                            ''', (qe_ids, ))
                    else:
                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except OSError as err:
                logging.info(
                    'event/table/session/row/%s:disconnected (role: %s)' %
                    (session_id, env['DB_USER']))

        return []
예제 #20
0
def application(env, start_response):
    request = Request(env)

    try:
        with map_errors_to_http(), cursor_for_request(request) as cursor:
            rowcount = 0
            # Text resource
            cursor.execute('''
                select r.content, m.mimetype
                from endpoint.resource r
                    join endpoint.mimetype m on r.mimetype_id = m.id
                where path = %s
                and active = true
            ''', (request.path,))
            text_resources = cursor.fetchall()
            rowcount += cursor.rowcount

            # Binary resource
            cursor.execute('''
                select r.content, m.mimetype
                from endpoint.resource_binary r
                    join endpoint.mimetype m on r.mimetype_id = m.id
                where path = %s
                and active = true
            ''', (request.path,))
            binary_resources = cursor.fetchall()
            rowcount += cursor.rowcount

            # Template resource
            # check for matching route
            cursor.execute('''
                select array_to_json(regexp_matches(%s, r.url_pattern)) as match from endpoint.template_route r
                ''', (request.path,))
            routes = cursor.fetchall()
            rowcount += cursor.rowcount

            # render template if we found one ^^.  only if we don't have other rows
            template_resources = None
            if routes != None:
                cursor.execute('''
                    select
                        endpoint.template_render(
                            t.id,
                            r.args::json,
                            array_to_json( regexp_matches(%s, r.url_pattern) )
                        ) as content, 
                        m.mimetype
                    from endpoint.template_route r
                        join endpoint.template t on r.template_id = t.id
                        join endpoint.mimetype m on t.mimetype_id = m.id
                ''', (request.path,))
                template_resources = cursor.fetchall()
#            else:
#                logging.info('HEEEEYYYYYYYY NO WE DID NOT GET a row')
#            cursor.execute('''
#                select
#                    id, regex_matches(%s, r.url_pattern),
#                    endpoint.render_template(t.id, r.args::json) as content, 'text/html' as mimetype, r.args
#                from template.template t
#                    join template.template_route r on r.template_id = t.id
#                where             ''', (request.path,))
#            template_resources = cursor.fetchall()
#            rowcount += cursor.rowcount

            # detect path collisions
            if rowcount > 1:
                raise MultipleChoices

            row = None

            if len(text_resources) == 1:
                row = text_resources[0]
            if len(binary_resources) == 1:
                row = binary_resources[0]
            if len(template_resources) == 1:
                row = template_resources[0]


### Commenting out until security can be audited...
###            # File resource
###            if row is None:
###                cursor.execute('''
###                    select f.content, m.mimetype
###                    from filesystem.file f
###                        left join endpoint.mimetype_extension e on e.extension = regexp_replace(f.name, '^.*\.', '')
###                        left join endpoint.mimetype m on m.id = e.mimetype_id
###                    where f.path = (select file_id from endpoint.resource_file where path=%s and active=true)
###                ''', (request.path,))
###                row = cursor.fetchone()
###
###
###            # Directory resource
###            # Question: only directories where indexes = true?
###            if row is None:
###                cursor.execute('''
###                    with dir as (
###                        select directory_id as dir_id
###                        from endpoint.resource_directory
###                        where path=%s and indexes=true
###                    )
###                    select path, name, last_mod, size, endpoint.is_indexed(path) as show from filesystem.directory where parent_id=(select dir_id from dir)
###                    union
###                    select path, name, last_mod, size, endpoint.is_indexed(path) as show from filesystem.file where directory_id=(select dir_id from dir)
###                ''', (request.path,))
###                rows = cursor.fetchall()
###
###                if len(rows):
###                    return Response(build_directory_index(request.path, rows), content_type='text/html')
###
###            # File-in-Directory resource
###            if row is None:
###                cursor.execute('''
###                    with dir as (
###                        select directory_id as dir_id, path, char_length(path) as path_length
###                        from endpoint.resource_directory
###                        where %s like path || '%%'
###                    )
###                    select f.content, m.mimetype
###                        from filesystem.file f
###                        left join endpoint.mimetype_extension e on e.extension = regexp_replace(f.name, '^.*\.', '')
###                        left join endpoint.mimetype m on m.id = e.mimetype_id
###                        where path = (select dir_id from dir) || substring(%s from (select path_length + 1 from dir))
###                ''', (request.path,request.path))
###                row = cursor.fetchone()

            # Should this redirect to /login?
            # That would mean: Resource Not Found = Resource Not Authorized
            # Which is accurate considering RLS hides unauthorized data
            # No because auth should occur in widgets, no redirecting
            if row is None:
                # Is this returning a 404?
                raise NotFound

            return Response(row.content, content_type='text/plain' if row.mimetype is None else row.mimetype)

    except HTTPException as e:
        return e
예제 #21
0
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            session_id = get_session_id(request, cursor)

            logging.info('event/table/session/row/%s:connected (role: %s)' % (session_id, env['DB_USER']))

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            cursor.execute('listen "event/table/session/rows/%i"' % session_id)

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] == 'subscribe':
                                        selector, type = cmd['args']['selector'].rsplit(':', 1)
                                        cursor.execute("select event.subscribe_session(%s, %s, %s);", (session_id, selector, type))

                                    elif cmd['method'] == 'unsubscribe':
                                        selector, type = cmd['args']['selector'].rsplit(':', 1)
                                        cursor.execute("select event.unsubscribe_session(%s, %s, %s);", (session_id, selector, type))

                                except Warning as err:
                                    logging.error(str(err))
                                    uwsgi.websocket_send(json.dumps({
                                        "method": "log",
                                        "args": {
                                            "level": "warning",
                                            "message": err.diag.message_primary
                                        }
                                    }))

                    elif fd == db_conn_fd:
                        db_connection.poll()

                        if db_connection.notifies:
                            del db_connection.notifies[:]

                            cursor.execute('''
                                select *
                                from event.session_queued_events_json(%s)
                            ''', (session_id,))

                            qe_ids = []
                            logging.info('event/table/session/row/%s:flushing_queue (role: %s)' % (session_id, env['DB_USER']))

                            for row in cursor:
                                uwsgi.websocket_send(json.dumps(row.event_json))
                                logging.info('event/table/session/row/%s:sent_json (role: %s)' % (session_id, env['DB_USER']))
                                qe_ids.append(row.queued_event_id)

                            cursor.execute('''
                                delete from event.queued_event qe
                                where qe.id = any(%s)
                            ''', (qe_ids,))
                    else:
                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except OSError as err:
                logging.info('event/table/session/row/%s:disconnected (role: %s)' % (session_id, env['DB_USER']))

        return []