Exemplo n.º 1
0
async def view_graphql_schema(request, datasette):
    database = request.url_vars.get("database")
    try:
        datasette.get_database(database)
    except KeyError:
        raise NotFound("Database does not exist")
    schema = await schema_for_database_via_cache(datasette, database=database)
    return Response.text(print_schema(schema))
Exemplo n.º 2
0
def robots_txt(datasette):
    config = datasette.plugin_config("datasette-block-robots") or {}
    literal = config.get("literal")
    disallow = []
    if literal:
        return Response.text(literal)
    disallow = config.get("disallow") or []
    if isinstance(disallow, str):
        disallow = [disallow]
    allow_only_index = config.get("allow_only_index")
    if allow_only_index:
        for database_name in datasette.databases:
            if database_name != "_internal":
                disallow.append(datasette.urls.database(database_name))
    if not disallow:
        disallow = ["/"]
    lines = ["User-agent: *"
             ] + ["Disallow: {}".format(item) for item in disallow]
    return Response.text("\n".join(lines))
Exemplo n.º 3
0
def handle_exception(datasette, request, exception):
    datasette._exception_hook_fired = (request, exception)
    if request.args.get("_custom_error"):
        return Response.text("_custom_error")
    elif request.args.get("_custom_error_async"):

        async def inner():
            return Response.text("_custom_error_async")

        return inner
Exemplo n.º 4
0
async def manage_db_group(scope, receive, datasette, request):
    db_name = unquote_plus(request.url_vars["database"])
    if not await datasette.permission_allowed(
        request.actor, "live-permissions-edit", db_name, default=False
    ):
        raise Forbidden("Permission denied")

    db = get_db(datasette)

    group_id = None
    results = db["groups"].rows_where("name=?", [f"DB Access: {db_name}"])
    for row in results:
        group_id = row["id"]
        break

    assert db_name in datasette.databases, "Non-existant database!"

    if not group_id and db_name not in BLOCKED_DB_ACTIONS:
        db["groups"].insert({
            "name": f"DB Access: {db_name}",
        }, pk="id", replace=True)
        return await manage_db_group(scope, receive, datasette, request)

    if request.method in ["POST", "DELETE"]:
        formdata = await request.post_vars()
        user_id = formdata["user_id"]

        if request.method == "POST":
            db["group_membership"].insert({
                "group_id": group_id,
                "user_id": user_id,
            }, replace=True)
        elif request.method == "DELETE":
            db["group_membership"].delete((group_id, user_id))
            return Response.text('', status=204)
        else:
            raise NotImplementedError(f"Bad method: {request.method}")

    perms_query = """
        select distinct user_id as id, lookup, value, description
        from group_membership join users
        on group_membership.user_id = users.id
        where group_membership.group_id=?
    """
    users = db.execute(perms_query, (group_id,))
    return Response.html(
        await datasette.render_template(
            "database_management.html", {
                "database": db_name,
                "users": users,
            }, request=request
        )
    )
Exemplo n.º 5
0
def register_routes(datasette):
    config = datasette.plugin_config("register-route-demo")
    if not config:
        return
    path = config["path"]

    def new_table(request):
        return Response.text("/db/table: {}".format(
            sorted(request.url_vars.items())))

    return [
        (r"/{}/$".format(path), lambda: Response.text(path.upper())),
        # Also serves to demonstrate over-ride of default paths:
        (r"/(?P<db_name>[^/]+)/(?P<table_and_format>[^/]+?$)", new_table),
    ]
Exemplo n.º 6
0
async def perms_crud(scope, receive, datasette, request):
    table = request.url_vars["table"]
    default_next = datasette.urls.path(f"/live_permissions/{table}")
    next = request.args.get("next", default_next)
    obj_id = request.url_vars["id"]

    if not await datasette.permission_allowed(
        request.actor, "live-permissions-edit", default=False
    ):
        raise Forbidden("Permission denied")

    assert table and obj_id, "Invalid URL"
    assert request.method in ["POST", "DELETE"], "Bad method"
    assert table in KNOWN_TABLES, "Bad table name provided"

    db = get_db(datasette)
    # POST is just dual update/create (depending on if id=="new")
    if request.method == "POST":
        formdata = await request.post_vars()

        if "csrftoken" in formdata:
            del formdata["csrftoken"]

        pk = "id"
        if table == "group_membership":
            pk = ("group_id", "user_id")
        db[table].insert(
            formdata, pk=pk, alter=False, replace=False
        )
        return Response.redirect(next)

    elif request.method == "DELETE":
        try:
            obj_id = int(obj_id)
        except ValueError:
            obj_id = tuple(int(i) for i in obj_id.split(","))
        db[table].delete(obj_id)
        return Response.text('', status=204)

    else:
        raise NotImplementedError("Bad HTTP method!")
Exemplo n.º 7
0
 async def one(datasette):
     return Response.text(
         (await datasette.get_database().execute("select 1 + 1")).first()[0]
     )
Exemplo n.º 8
0
 def new_table(request):
     return Response.text("/db/table: {}".format(
         sorted(request.url_vars.items())))
Exemplo n.º 9
0
 async def options(self, request, *args, **kwargs):
     r = Response.text("ok")
     if self.ds.cors:
         add_cors_headers(r.headers)
     return r
Exemplo n.º 10
0
def test_response_text():
    response = Response.text("Hello from text")
    assert 200 == response.status
    assert "Hello from text" == response.body
    assert "text/plain; charset=utf-8" == response.content_type
Exemplo n.º 11
0
 async def delete(self, request, *args, **kwargs):
     return Response.text("Method not allowed", status=405)
Exemplo n.º 12
0
def robots_txt():
    return Response.text("Sitemap: https://www.niche-museums.com/sitemap.xml")
Exemplo n.º 13
0
async def view_graphql(request, datasette):
    if request.method == "OPTIONS":
        return Response.text("ok",
                             headers=CORS_HEADERS if datasette.cors else {})

    body = await post_body(request)
    database = request.url_vars.get("database")

    try:
        datasette.get_database(database)
    except KeyError:
        raise NotFound("Database does not exist")

    if not body and "text/html" in request.headers.get("accept", ""):
        return Response.html(
            await datasette.render_template("graphiql.html", {
                "database": database,
            },
                                            request=request),
            headers=CORS_HEADERS if datasette.cors else {},
        )

    schema = await schema_for_database_via_cache(datasette, database=database)

    if request.args.get("schema"):
        return Response.text(print_schema(schema))

    incoming = {}
    if body:
        incoming = json.loads(body)
        query = incoming.get("query")
        variables = incoming.get("variables")
        operation_name = incoming.get("operationName")
    else:
        query = request.args.get("query")
        variables = request.args.get("variables", "")
        if variables:
            variables = json.loads(variables)
        operation_name = request.args.get("operationName")

    if not query:
        return Response.json(
            {"error": "Missing query"},
            status=400,
            headers=CORS_HEADERS if datasette.cors else {},
        )

    config = datasette.plugin_config("datasette-graphql") or {}
    context = {
        "time_started":
        time.monotonic(),
        "time_limit_ms":
        config.get("time_limit_ms") or DEFAULT_TIME_LIMIT_MS,
        "num_queries_executed":
        0,
        "num_queries_limit":
        config.get("num_queries_limit") or DEFAULT_NUM_QUERIES_LIMIT,
    }

    result = await graphql(
        schema,
        query,
        operation_name=operation_name,
        variable_values=variables,
        context_value=context,
        executor=AsyncioExecutor(),
        return_promise=True,
    )
    response = {"data": result.data}
    if result.errors:
        response["errors"] = [format_error(error) for error in result.errors]

    return Response.json(
        response,
        status=200 if not result.errors else 500,
        headers=CORS_HEADERS if datasette.cors else {},
    )
Exemplo n.º 14
0
 async def inner():
     return Response.text("_custom_error_async")
Exemplo n.º 15
0
 async def two(request):
     name = request.url_vars["name"]
     greeting = request.args.get("greeting")
     return Response.text("{} {}".format(greeting, name))
Exemplo n.º 16
0
 async def two(request):
     name = request.url_vars["name"]
     greeting = request.args.get("greeting")
     return Response.text(f"{greeting} {name}")
Exemplo n.º 17
0
def render_yaml(rows):
    return Response.text(dump([dict(r) for r in rows], sort_keys=False))
Exemplo n.º 18
0
def register_routes(datasette):
    config = datasette.plugin_config("register-route-demo")
    if not config:
        return
    path = config["path"]
    return [(r"/{}/$".format(path), lambda: Response.text(path.upper()))]
Exemplo n.º 19
0
 def options(self, request, *args, **kwargs):
     r = Response.text("ok")
     if self.ds.cors:
         r.headers["Access-Control-Allow-Origin"] = "*"
     return r
Exemplo n.º 20
0
async def robots():
    return Response.text(robots_text)