Exemplo n.º 1
0
def build_authcheck(request, ti='', forceprivate=False, action=None):
    """Build an SQL WHERE clause which enforces access restrictions.
    Will pull any credentials out of the request object passed in.

    "action" should either be None, in which case the subscription
    permissions will be used, or one of the can_XXX permissions in the
    permission table.
    """
    query = "sub.id = s.subscription_id AND "
    if not 'private' in request.args and not forceprivate:
        query += "(sub%s.public " % ti
    else:
        query += "(false "

    if 'key' in request.args:
        query += 'OR ( (' + ' OR '.join(["sub.key = %s" % escape_string(x + ti)
                                      for x in request.args['key']]) + \
                                       ') )'

    if (settings.conf['features']['permissions'] and 'key' in request.args
            and action is not None):
        # add permissions granted by the permissions table
        query += """OR ( (sub.id IN (SELECT perm_sub.subscription_id 
FROM permission perm, permission_subscriptions perm_sub
WHERE perm.id = perm_sub.permission_id AND 
 ((perm.valid_after IS NULL OR perm.valid_after < current_timestamp) AND
  (perm.valid_until IS NULL or perm.valid_until > current_timestamp)) AND (""" + \
            ' OR '.join(('perm.key = %s' % escape_string(x + ti)
                         for x in request.args['key'])) + \
                         (') AND perm.can_%s IS true)' % action) + \
                         ') AND sub.id = s.subscription_id)'

    query += ")"
    return query
Exemplo n.º 2
0
def build_setstring(setvals, wherevals):
    #  set tags 
    regex = None
    regex_tag = None
    for stmt in wherevals:
        if stmt.op == ast.Statement.OP_REGEX:
            if regex == None:
                regex = stmt
            else:
                raise qg.QueryException("Too many regexes in set.  Only one supported!")

    if regex == None:
        new_tags = ' || '.join(map(lambda (t,v): "hstore(%s, %s)" % 
                                   (escape_string(t), escape_string(v)),
                                   setvals))
    else:
        new_tags = ' || '.join(map(lambda (t,v): "hstore(%s, regexp_replace(metadata -> %s, '^.*%s.*$', %s))" % 
                                   (escape_string(t), 
                                    regex.args[0],
                                    regex.args[1][1:-1].replace('\\\\', '\\'),
                                    escape_string(v).replace('\\\\', '\\')),
                                   setvals))
        regex_tag = regex.args[0][1:-1]

    return new_tags, regex_tag
Exemplo n.º 3
0
def build_setstring(setvals, wherevals):
    #  set tags
    regex = None
    for stmt in wherevals:
        if stmt.op == ast.Statement.OP_REGEX:
            if regex == None:
                regex = stmt
            else:
                raise qg.QueryException(
                    "Too many regexes in set.  Only one supported!")

    if regex == None:
        new_tags = ' || '.join(
            map(
                lambda (t, v): "hstore(%s, %s)" %
                (escape_string(t), escape_string(v)), setvals))
    else:
        new_tags = ' || '.join(
            map(
                lambda (t, v):
                "hstore(%s, regexp_replace(metadata -> %s, '^.*%s.*$', %s))" %
                (escape_string(t), regex.args[0], regex.args[1][1:-1].replace(
                    '\\\\', '\\'), escape_string(v).replace('\\\\', '\\')),
                setvals))
    return new_tags
Exemplo n.º 4
0
def build_authcheck(request, ti='', forceprivate=False, action=None):
    """Build an SQL WHERE clause which enforces access restrictions.
    Will pull any credentials out of the request object passed in.

    "action" should either be None, in which case the subscription
    permissions will be used, or one of the can_XXX permissions in the
    permission table.
    """
    if not 'private' in request.args and not forceprivate:
        query = "(sub%s.public " % ti
    else:
        query = "(false "

    if 'key' in request.args:
        query += 'OR ( (' + ' OR '.join(["sub.key = %s" % escape_string(x + ti)
                                      for x in request.args['key']]) + \
                                       ') AND sub.id = s.subscription_id) '

    if (settings.conf['features']['permissions'] and 
        'key' in request.args and action is not None):
        # add permissions granted by the permissions table
        query += """OR ( (sub.id IN (SELECT perm_sub.subscription_id 
FROM permission perm, permission_subscriptions perm_sub
WHERE perm.id = perm_sub.permission_id AND 
 ((perm.valid_after IS NULL OR perm.valid_after < current_timestamp) AND
  (perm.valid_until IS NULL or perm.valid_until > current_timestamp)) AND (""" + \
            ' OR '.join(('perm.key = %s' % escape_string(x + ti)
                         for x in request.args['key'])) + \
                         (') AND perm.can_%s IS true)' % action) + \
                         ') AND sub.id = s.subscription_id)'

    query += ")"
    return query
Exemplo n.º 5
0
def add_formula_restrictions(c_restrict, f_restrict):
    extra = []
    for k, v in SetDict(f_restrict):
        if k != "uuid":
            extra.append("((s.metadata -> %s) ~ %s)" % (escape_string(k), escape_string(v)))
        else:
            extra.append("(s.uuid = %s)" % escape_string(v))
    if len(extra):
        return c_restrict + " AND (" + " OR ".join(extra) + ")"
    else:
        return c_restrict
Exemplo n.º 6
0
def add_formula_restrictions(c_restrict, f_restrict):
    extra = []
    for k, v in SetDict(f_restrict):
        if k != 'uuid':
            extra.append('((s.metadata -> %s) ~ %s)' % 
                         (escape_string(k), escape_string(v)))
        else:
            extra.append('(s.uuid = %s)' % escape_string(v))
    if len(extra):
        return c_restrict + ' AND (' + ' OR '.join(extra) + ')'
    else:
        return c_restrict
Exemplo n.º 7
0
def add_formula_restrictions(c_restrict, f_restrict):
    extra = []
    for k, v in SetDict(f_restrict):
        if k != 'uuid':
            extra.append('((s.metadata -> %s) ~ %s)' %
                         (escape_string(k), escape_string(v)))
        else:
            extra.append('(s.uuid = %s)' % escape_string(v))
    if len(extra):
        return c_restrict + ' AND (' + ' OR '.join(extra) + ')'
    else:
        return c_restrict
Exemplo n.º 8
0
def p_selector(t):
    """selector : tag_list
                | '*'
                | DISTINCT LVALUE
                | DISTINCT """
    if t[1] == "distinct":
        if len(t) == 2:
            t[0] = selector("DISTINCT skeys(s.metadata)", ext_non_null)
        elif t[2] == "uuid":
            t[0] = selector("DISTINCT s.uuid", ext_non_null)
        else:
            t[0] = selector("DISTINCT (s.metadata -> %s)" % escape_string(t[2]), ext_non_null)
    else:
        t[0] = make_tag_select(t[1])
Exemplo n.º 9
0
def p_selector(t):
    """selector : tag_list
                | '*'
                | DISTINCT LVALUE
                | DISTINCT """
    if t[1] == 'distinct':
        if len(t) == 2:
            t[0] = selector("DISTINCT skeys(s.metadata)", ext_non_null)
        elif t[2] == 'uuid':
            t[0] = selector("DISTINCT s.uuid", ext_non_null)
        else:
            t[0] = selector("DISTINCT (s.metadata -> %s)" % escape_string(t[2]),
                            ext_non_null)
    else:
        t[0] = make_tag_select(t[1])
Exemplo n.º 10
0
def p_statement_binary(t):
    """statement_binary : LVALUE '=' QSTRING
                        | LVALUE LIKE QSTRING
                        | LVALUE TILDE QSTRING
    """
    if t[1] == 'uuid':
        t[0] = 's.uuid %s %s' % (t[2], escape_string(t[3]))
    else:
        if t[2] == '=':
            q = "s.metadata @> hstore(%s, %s)" % (escape_string(t[1]), 
                                                  escape_string(t[3]))
        elif t[2] == 'like':
            q = "(s.metadata -> %s) LIKE %s" % (escape_string(t[1]), 
                                                escape_string(t[3]))
        elif t[2] == '~':
            q = "(s.metadata -> %s) ~ %s" % (escape_string(t[1]), 
                                             escape_string(t[3]))

        t[0] = '(s.metadata ? %s) AND (%s)' % (escape_string(t[1]), q)
Exemplo n.º 11
0
def make_set_rv(t):
    # build the query for a set expression
    if len(t) > 3:
        # if there is a where clause, grab it
        where_clause = t[4]
    else:
        # if no where clause, just do something fast that matches
        # everything
        where_clause = ast.Statement(ast.Statement.OP_UUID)
    noop = "noop" in t.parser.request.args

    # build a list of what tags we're updating, as well as the
    # name of the regex tag.  We're currently not smart enough to
    # deal with more than one regex match in a set statement, due
    # to issues with back references.
    new_tags, regex_tag = build_setstring(t[2], where_clause)
    tag_list = [v[0] for v in t[2]]
    if regex_tag: tag_list.append(regex_tag)

    # if we're in noop mode, we need to tweak the SQL
    if not noop:
        command = "UPDATE stream SET metadata = metadata || "
        from_stmt = ""
    else:
        command = "SELECT uuid, "
        from_stmt = "FROM stream"

    # build the first part of the query that depends on if this is a noop
    q = "%(command)s %(hstore_expression)s %(from_stmt)s WHERE ID IN" % {
        "command": command,
        "hstore_expression": new_tags,
        "from_stmt": from_stmt
    }

    # the where caluse always looks the same
    q += "(SELECT s.id FROM stream s, subscription sub " + \
        "WHERE (" + where_clause.render() + ") AND s.subscription_id = sub.id AND " + \
        qg.build_authcheck(t.parser.request, forceprivate=True)  + ") "

    if not noop:
        # return the list of modifications.  if this was a noop we
        # get this for free.
        q += " RETURNING uuid, slice(metadata, ARRAY[" + \
            ','.join((escape_string(v) for v in tag_list)) + "])"
    return lambda x: ext_set(tag_list, x), q
Exemplo n.º 12
0
def make_set_rv(t):
    # build the query for a set expression
    if len(t) > 3:
        # if there is a where clause, grab it
        where_clause = t[4]
    else:
        # if no where clause, just do something fast that matches
        # everything
        where_clause = ast.Statement(ast.Statement.OP_UUID)
    noop = "noop" in t.parser.request.args

    # build a list of what tags we're updating, as well as the
    # name of the regex tag.  We're currently not smart enough to
    # deal with more than one regex match in a set statement, due
    # to issues with back references.
    new_tags, regex_tag = build_setstring(t[2], where_clause)
    tag_list = [v[0] for v in t[2]]
    if regex_tag: tag_list.append(regex_tag)

    # if we're in noop mode, we need to tweak the SQL
    if not noop: 
        command = "UPDATE stream SET metadata = metadata || "
        from_stmt = ""
    else:
        command = "SELECT uuid, "
        from_stmt = "FROM stream"

    # build the first part of the query that depends on if this is a noop
    q = "%(command)s %(hstore_expression)s %(from_stmt)s WHERE ID IN" % {
        "command": command,
        "hstore_expression": new_tags,
        "from_stmt": from_stmt }

    # the where caluse always looks the same
    q += "(SELECT s.id FROM stream s, subscription sub " + \
        "WHERE (" + where_clause.render() + ") AND s.subscription_id = sub.id AND " + \
        qg.build_authcheck(t.parser.request, forceprivate=True, action='set')  + ") " 

    if not noop:
        # return the list of modifications.  if this was a noop we
        # get this for free.
        q += " RETURNING uuid, slice(metadata, ARRAY[" + \
            ','.join((escape_string(v) for v in tag_list)) + "])"
    return lambda x: ext_set(tag_list, x), q
Exemplo n.º 13
0
 def make_clause(x):
     if x == 'uuid':
         return "(s.uuid)"
     else:
         return "(s.metadata -> %s)" % escape_string(x)
Exemplo n.º 14
0
 def make_clause(x):
     if x == 'uuid':
         return "(s.uuid)"
     else:
         return "(s.metadata -> %s)" % escape_string(x)
Exemplo n.º 15
0
def p_statement_unary(t):
    """statement_unary : HAS LVALUE"""
    if t[1] == 'has':
        t[0] = 's.metadata ? %s' % escape_string(t[2])
Exemplo n.º 16
0
def p_query(t):
    """query : SELECT selector WHERE statement
             | SELECT selector
             | SELECT data_clause WHERE statement
             | DELETE tag_list WHERE statement
             | DELETE WHERE statement
             | SET set_list WHERE statement
             | APPLY apply_statement
             | HELP
             | HELP LVALUE
             """
    if t[1] == 'select': 
        if len(t) == 5:
            t[0] = make_select_rv(t, t[2], t[4])
        elif len(t) == 3:
            t[0] = make_select_rv(t, t[2])
        
    elif t[1] == 'delete':
        # a new delete inner statement enforces that we only delete
        # things which we have the key for.
        if t[2] == 'where':
            # delete the whole stream, gone.  this also deletes the
            # data in the backend readingdb.
            t[0] = ext_deletor, \
                """DELETE FROM stream WHERE id IN (
                     SELECT s.id FROM stream s, subscription sub 
                     WHERE (%(restrict)s) AND s.subscription_id = sub.id AND 
                     (%(auth)s)
                   ) RETURNING id, uuid
                """ % { 
                'restrict': t[3],
                'auth': qg.build_authcheck(t.parser.request, forceprivate=True) 
                }
        else:
            # this alters the tags but doesn't touch the data
            del_tags = ', '.join(map(escape_string, t[2]))
            q = "UPDATE stream SET metadata = metadata - ARRAY[" + del_tags + \
                "] WHERE id IN " + \
                "(SELECT s.id FROM stream s, subscription sub " + \
                "WHERE (" + t[4] + ") AND s.subscription_id = sub.id AND " + \
                qg.build_authcheck(t.parser.request, forceprivate=True)  + ")"
            t[0] = None, q

    elif t[1] == 'set':
        #  set tags 
        new_tags = ' || '.join(map(lambda (t,v): "hstore(%s, %s)" % 
                                   (escape_string(t), escape_string(v)),
                               t[2]))
        q = "UPDATE stream SET metadata = metadata || " + new_tags + \
            " WHERE id IN "  + \
            "(SELECT s.id FROM stream s, subscription sub " + \
            "WHERE (" + t[4] + ") AND s.subscription_id = sub.id AND " + \
            qg.build_authcheck(t.parser.request, forceprivate=True)  + ")"
        t[0] = None, q

    elif t[1] == 'apply':
        t[0] = t[2]
    elif t[1] == 'help':
        if len(t) == 2:
            t[0] = help.help(), None
        else:
            t[0] = help.help(t[2]), None