Files
lasuite-drive/docs/resource_server.md
T
Nathan Vasse 8f47646dff (backend) apply per-audience attributes to external api items
External services consuming the resource server API may need items they
create to carry specific attributes, typically quota_excluded so their
uploads do not consume the user quota.

The new EXTERNAL_API_AUD_ITEM_ATTRIBUTES setting maps a token audience
to the attributes applied at creation. The lookup is a hook on the item
viewset overridden only in the resource server viewset, so both the
root create and children creation paths are covered while the regular
API remains unaffected.
2026-08-03 10:20:45 +02:00

6.2 KiB

Use Drive as a Resource Server

Drive implements resource server, so it means it can be used from an external app to perform some operation using the dedicated API.

Note: This feature might be subject to future evolutions. The API endpoints, configuration options, and behavior may change in future versions.

Prerequisites

In order to activate the resource server on Drive you need to setup the following environement variables

OIDC_RESOURCE_SERVER_ENABLED=True
OIDC_OP_URL=
OIDC_OP_INTROSPECTION_ENDPOINT=
OIDC_RS_CLIENT_ID=
OIDC_RS_CLIENT_SECRET=
OIDC_RS_AUDIENCE_CLAIM=
OIDC_RS_ALLOWED_AUDIENCES=

It implements the resource server using django-lasuite, see the documentation

Customise allowed routes

Configure the EXTERNAL_API setting to control which routes and actions are available in the external API. Set it via the EXTERNAL_API environment variable (as JSON) or in Django settings.

Default configuration:

EXTERNAL_API = {
    "items": {
        "enabled": True,
        "actions": ["list", "retrieve", "children", "upload_ended"],
    },
    "item_access": {
        "enabled": False,
        "actions": [],
    },
    "item_invitation": {
        "enabled": False,
        "actions": [],
    },
    "users": {
        "enabled": True,
        "actions": ["get_me"],
    }
}

Endpoints:

  • items: Controls /external_api/v1.0/items/. Available actions: list, retrieve, create, update, partial_update, destroy, children, upload_ended, move, restore, trashbin, hard_delete, tree, breadcrumb, link_configuration, favorite, media_auth, wopi
  • item_access: Controls /external_api/v1.0/items/{id}/accesses/. Available actions: list, retrieve, create, update, partial_update, destroy
  • item_invitation: Controls /external_api/v1.0/items/{id}/invitations/. Available actions: list, retrieve, create, update, partial_update, destroy

Each endpoint has enabled (boolean) and actions (list of allowed actions). Only actions explicitly listed are accessible.

Customise created item attributes per audience

Configure the EXTERNAL_API_AUD_ITEM_ATTRIBUTES setting to apply extra attributes to items created through the external API, depending on the token audience of the request (the claim configured by OIDC_RS_AUDIENCE_CLAIM). Set it via the EXTERNAL_API_AUD_ITEM_ATTRIBUTES environment variable (as JSON) or in Django settings.

EXTERNAL_API_AUD_ITEM_ATTRIBUTES = {
    "some_audience": {
        "quota_excluded": True,
    },
}

With this configuration, every item created by a request authenticated with the some_audience audience is excluded from its creator's storage quota computation. Audiences without an entry keep the default item attributes.

Request Drive

In order to request drive from an external resource provider, you need to implement the basic setup of django-lasuite Using the OIDC Authentication Backend to request a resource server

Then you can requests some routes that are available at /external_api/v1.0/*, here are some examples of what you can do.

Upload a file

Here is an example of a view that create a file on the main workspace in Drive.

    @method_decorator(refresh_oidc_access_token)
    def upload_file(self, request):
        """
        Create a new file in the main workspace.
        """

        # Get the access token from the session
        access_token = request.session.get('oidc_access_token')

        # Get the main workspace
        response = requests.get(
            f"{settings.DRIVE_API}/items/",
            headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"},
        )
        response.raise_for_status()
        data = response.json()
        items = data['results']
        main_workspace = None
        for item in items:
            if item['main_workspace']:
                main_workspace = item
                break

        if not main_workspace:
            return drf.response.Response(status=404, data={"error": "No main workspace found"})

        # Create a new file in the main workspace
        response = requests.post(
            f"{settings.DRIVE_API}/items/{main_workspace['id']}/children/",
            json={
                "type": "file",
                "filename": "test.txt",
            },
            headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"},
        )
        response.raise_for_status()
        item = response.json()
        policy = item['policy']

        # Upload file content using the presigned URL
        import os
        sample_file_path = os.path.join(os.path.dirname(__file__), "sample.txt")
        with open(sample_file_path, "rb") as f:
            upload_response = requests.put(
                policy,
                data=f.read(),
                headers={
                    "Content-Type": "text/plain",
                    "x-amz-acl": "private"
                }
            )
            upload_response.raise_for_status()

        # Tell the Drive API that the upload is ended
        response = requests.post(
            f"{settings.DRIVE_API}/items/{item['id']}/upload-ended/",
            json={},
            headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"},
        )
        response.raise_for_status()

        return drf.response.Response(data)

Create a new folder

Using the same logic as the previous example, you can create a folder in the main workspace.

response = requests.post(
    f"{settings.DRIVE_API}/items/{main_workspace['id']}/children/",
    json={
        "type": "folder",
        "title": "My folder",
    },
    headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"},
)

Get user information

The same way, you can use the /me endpoint to get user information.

response = requests.get(
    "{settings.DRIVE_API}/users/me/",
    headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"},
)