예제 #1
0
def row(user, database, table, row, format=None):
    require(user, database, 'read', format)
    _table = _get_table(user, database, table, format)
    try:
        row = int(row)
    except ValueError:
        raise WebstoreException('Invalid row ID: %s' % row,
                                format,
                                state='error',
                                code=400)
    if row == 0:
        raise WebstoreException('Starting at offset 1 to allow header row',
                                format,
                                state='error',
                                code=400)
    params, select_args = _request_query(_table, request.args, format)
    select_args['limit'] = 1
    select_args['offset'] = row - 1
    try:
        statement = _table.table.select('', **select_args)
        log.debug("Read row: %s" % statement)
        results = _table.bind.execute(statement)
    except OperationalError, oe:
        raise WebstoreException('Invalid query: %s' % oe.message,
                                format,
                                state='error',
                                code=400)
예제 #2
0
def sql(user, database, format=None):
    """ Execute an SQL statement on the database. """
    # TODO: do we really, really need this?
    if request.content_type == 'text/sql':
        query = request.data
        params = None
        attaches = []
    elif request.content_type.lower() == 'application/json':
        query = request.json.get('query', '')
        params = request.json.get('params')
        attaches = request.json.get('attach', [])
    else:
        raise WebstoreException('Only text/sql, application/json is supported',
                                format,
                                state='error',
                                code=400)
    try:
        if has(user, database, 'delete'):
            db = db_factory.create(user, database)
        else:
            require(user, database, 'read', format)
            db = db_factory.create_readonly(user, database)
    except NamingException, ne:
        raise WebstoreException('Invalid DB name: %s' % ne.field,
                                format,
                                state='error',
                                code=400)
예제 #3
0
def _get_table(user, database, table, format):
    """ Locate a named table or raise a 404. """
    try:
        db = db_factory.create(user, database)
    except NamingException, ne:
        raise WebstoreException('Invalid DB name: %s' % ne.field,
                format, state='error', code=400)
예제 #4
0
def upsert(user, database, table, format=None):
    require(user, database, 'write', format)
    try:
        db = db_factory.create(user, database)
    except NamingException, ne:
        raise WebstoreException('Invalid DB name: %s' % ne.field,
                format, state='error', code=400)
예제 #5
0
def never_login(request):
    if 'Authorization' in request.headers:
        raise WebstoreException('Invalid username or password!',
                                None,
                                state='error',
                                code=401)
    return None
예제 #6
0
파일: ckan.py 프로젝트: pr3ssh/webstore
def check_ckan_login(request):
    """ Connect to a specified CKAN database via SQLAlchemy and 
    try to find the user that is authenticating. 
    """
    db_uri = app.config.get('CKAN_DB_URI')
    if db_uri is None:
        log.warn("No CKAN_DB_URI given, cannot authenticate!")
        return False
    if 'Authorization' in request.headers:
        authorization = request.headers.get('Authorization')
        authorization = authorization.split(' ', 1)[-1]
        user, password = authorization.decode('base64').split(':', 1)
        engine = create_engine(db_uri, poolclass=NullPool)
        meta = MetaData()
        meta.bind = engine
        table = Table('user', meta, autoload=True)
        results = engine.execute(table.select(table.c.name == user))
        # TODO: check for multiple matches, never trust ckan.
        record = results.first()
        if record is not None and check_hashed_password(
                password, record['password']):
            return user
        raise WebstoreException('Invalid username or password!',
                                None,
                                state='error',
                                code=401)
    return None
예제 #7
0
def delete(user, database, table, format=None):
    require(user, database, 'delete', format)
    _table = _get_table(user, database, table, format)
    _table.drop()
    log.debug("Dropping: %s" % _table.table.name)
    _table.commit()
    raise WebstoreException('Table dropped: %s' % table,
                            format, state='success', code=410)
예제 #8
0
def index(user, database, format=None):
    """ Give a list of all tables in the database. """
    require(user, database, 'read', format)
    try:
        db = db_factory.create(user, database)
    except NamingException, ne:
        raise WebstoreException('Invalid name: %s' % ne.field,
                format, state='error', code=400)
예제 #9
0
def read(user, database, table, format=None):
    require(user, database, 'read', format)
    _table = _get_table(user, database, table, format)
    params, select_args = _request_query(_table, request.args,
                                         format)
    try:
        clause = _table.args_to_clause(params)
    except KeyError, ke:
        raise WebstoreException('Invalid filter: %s' % ke,
                format, state='error', code=400)
예제 #10
0
def require(user, database, action, format):
    """ Require the current user to have the right to 
    execute `action` on `database` of `user`. If this 
    right is not given, raise an exception. 
    """
    if not has(user, database, action):
        raise WebstoreException('No permission to %s %s' % (action, database),
                                format,
                                state='error',
                                code=403)
예제 #11
0
def distinct(user, database, table, column, format=None):
    require(user, database, 'read', format)
    _table = _get_table(user, database, table, format)
    if not column in _table.table.columns:
        raise WebstoreException('No such column: %s' % column,
                format, state='error', code=404)
    params, select_args = _request_query(_table, request.args,
                                         format)
    select_args['distinct'] = True
    if not len(select_args['order_by']):
        select_args['order_by'].append(desc('_count'))
    try:
        col = _table.table.c[column]
        statement = select([col, func.count(col).label('_count')], 
                group_by=[col], **select_args)
        log.debug("Distinct: %s" % statement)
        results = _table.bind.execute(statement)
    except OperationalError, oe:
        raise WebstoreException('Invalid query: %s' % oe.message,
            format, state='error', code=400)
예제 #12
0
def sw_auth(request):
    """ Authenticate an incoming request. """
    current_app.sw_scrapername = request.headers.get('X-Scrapername')
    if current_app.sw_scrapername is not None:
        answer = sha256(current_app.sw_scrapername + \
                        current_app.config['SW_SECRET']).hexdigest()
        candidate = request.headers.get('X-Scraper-Verified')
        if candidate != answer:
            raise WebstoreException('Invalid ScraperWiki verification!',
                                    None,
                                    state='error',
                                    code=401)
예제 #13
0
def databases(user, format=None):
    """ Give a list of all databases owned by the user. """
    #require(user, database, 'read', format)
    try:
        databases = []
        for database in db_factory.databases_by_user(user):
            url = url_for('webstore.index', user=user, database=database)
            databases.append({'name': database, 'url': url})
        return render_table(request, databases, ['name', 'url'], format)
    except NamingException, ne:
        raise WebstoreException('Invalid name: %s' % ne.field,
                format, state='error', code=400)
예제 #14
0
def databases(user, format=None):
    """ Give a list of all databases owned by the user. """
    #require(user, database, 'read', format)
    try:
        databases = []

        # TODO: this is a hack, find a nicer way to do this
        #
        # we want to allow user names to contain a '.', eg: 'thedatahub.org'
        # this breaks the routing for this function
        #
        # so if format exists, check that it should not be part of the user name
        if format:
            try:
                user_databases = db_factory.databases_by_user(user + '.' +
                                                              format)
                user = user + '.' + format
            except UserNotFound:
                user_databases = db_factory.databases_by_user(user)
        else:
            user_databases = db_factory.databases_by_user(user)

        for database in user_databases:
            url = url_for('webstore.index', user=user, database=database)
            databases.append({'name': database, 'url': url})
        return render_table(request, databases, ['name', 'url'], format)
    except UserNotFound:
        raise WebstoreException('User not found',
                                format,
                                state='error',
                                code=404)
    except NamingException, ne:
        raise WebstoreException('Invalid name: %s' % ne.field,
                                format,
                                state='error',
                                code=400)
예제 #15
0
def _request_query(_table, _params, format):
    """ From a set of query parameters, apply those that
    affect a query result set, e.g. sorting, limiting and 
    offsets.

    Returns a tuple of the remaining query parameters and
    a curried call to the database.
    """
    params = _params.copy()
    if '_callback' in params:
        params.pop('_callback')

    try:
        limit = int(params.pop('_limit', None)) \
                    if '_limit' in params else None
        offset = int(params.pop('_offset', None)) \
                    if '_offset' in params else None
    except ValueError, ve:
        raise WebstoreException('Invalid value: %s' % ve,
                                format, state='error', code=400)
예제 #16
0
파일: ckan.py 프로젝트: rzs840707/webstore
def check_ckan_login(request):
    """ Connect to a specified CKAN database via SQLAlchemy and 
    try to find the user that is authenticating. 
    """
    db_uri = app.config.get('CKAN_DB_URI')
    if db_uri is None:
        log.warn("No CKAN_DB_URI given, cannot authenticate!")
        return False
    if 'Authorization' in request.headers:
        apikey = request.headers.get('Authorization')
        engine = create_engine(db_uri, poolclass=NullPool)
        meta = MetaData()
        meta.bind = engine
        table = Table('user', meta, autoload=True)
        results = engine.execute(table.select(table.c.apikey == apikey))
        # TODO: check for multiple matches, never trust ckan.
        record = results.first()
        if record is not None:
            return record['name']
        raise WebstoreException('Invalid apikey!',
                                None,
                                state='error',
                                code=401)
    return None
예제 #17
0
@store.before_app_request
def jsonp_callback_register():
    # This is a slight hack to not make JSON-P callback names 
    # end up in the query string, we'll keep it around on the 
    # request global and then read it in the table generator.
    g.callback = request.args.get('_callback')

def _get_table(user, database, table, format):
    """ Locate a named table or raise a 404. """
    try:
        db = db_factory.create(user, database)
    except NamingException, ne:
        raise WebstoreException('Invalid DB name: %s' % ne.field,
                format, state='error', code=400)
    if not table in db:
        raise WebstoreException('No such table: %s' % table,
                format, state='error', code=404)
    return db[table]

def _request_query(_table, _params, format):
    """ From a set of query parameters, apply those that
    affect a query result set, e.g. sorting, limiting and 
    offsets.

    Returns a tuple of the remaining query parameters and
    a curried call to the database.
    """
    params = _params.copy()
    if '_callback' in params:
        params.pop('_callback')

    try: