# Explicit permissions API

Sourcegraph allows site administrators to explicitly set repository permissions
through the [Sourcegraph API](/api). This is an alternative to other mechanisms,
which involve directly talking to the code host.

The Sourcegraph API is a versioned external API introduced in
[Sourcegraph 7.0](/api). The full API surface, including the operations
documented here, can be browsed at `/api-reference` on your instance (e.g.
`https://sourcegraph.example.com/api-reference`), where you can also download
the OpenAPI schema.

> NOTE: The [Sourcegraph GraphQL debug API](/api/graphql) also exposes some
> explicit-permissions operations for diagnostics and tooling, but the
> Sourcegraph API is the recommended interface for integrations.

## Permissions mechanisms in parallel

If you want to use explicit permissions management alongside permissions
synchronised from code hosts, read section [permission mechanisms in parallel here](/admin/permissions/#permissions-mechanisms-in-parallel).

## Recommendations

We only recommend using the explicit permissions API in cases where the other
methods are not possible or effective. For example, if a code host does not
support permission syncing/webhooks, or if it would take an unreasonable amount
of resources/time to sync permissions from the code host.

It's also a good idea to use the explicit permissions API if the source of
truth for the code host permissions is already defined in some external
system, e.g. LDAP group membership. In that case, it might be less resource
intensive to sync the permissions from the external source of truth directly
via a periodically running routine.

## SLA

Sourcegraph's SLA is that **p95 of write requests to the explicit permissions
API will be resolved within 10 seconds**.

Sourcegraph does not provide an SLA for how fresh the permissions are, since
the data is provided as-is to the API.

## Disadvantages

It is important to note that when using the explicit permissions API, the
permissions are written to the database as provided, without further
verification that such permissions exist on the code host side.

Keeping the permissions in sync and fresh is the responsibility of the site
admins.

## Licensing

The explicit permissions API requires the **Explicit Permissions API** license
feature. Calls made on an instance whose license does not include this feature
fail with a `FailedPrecondition` error.

## Configuration

To enable the permissions API, add the following to the [site configuration](/admin/config/site-config):

```json
"permissions.userMapping": {
    "enabled": true,
    "bindID": "username"
}
```

The `bindID` value specifies how to uniquely identify users when setting
permissions:

- `username`: You can set permissions for users by specifying their Sourcegraph
  usernames. Using usernames is **preferred**, as usernames are required to be
  unique for each user.
- `email`: You can set permissions for users by specifying their email
  addresses (which must be verified primary emails associated with their
  Sourcegraph user account). This method can lead to unexpected results if
  there are multiple Sourcegraph user accounts with the same verified email
  address. Also, the email address is case-sensitive, so it should be exactly
  the same as set in the Sourcegraph UI.

After you enable the permissions API, you must set permissions to allow users
to view repositories (site admins bypass all permissions checks and can always
view all repositories).

> NOTE: If you were previously using [permissions syncing](/admin/permissions/syncing),
> e.g. syncing permissions from GitHub, then those permissions are used as the
> initial state after enabling explicit permissions. Otherwise, the initial
> state is for all repositories to have an empty set of authorized users, so
> users will not be able to view any repositories.

> NOTE: In some cases, in order for the repo permissions to be enforced, you
> must re-save the code host connection configuration with some modification
> to the JSON after enabling the permissions API.

## Authentication and authorization

The Sourcegraph API accepts token-based authentication only — browser session
cookies are **not** accepted. Pass a Sourcegraph access token as a Bearer
token in the `Authorization` header:

```
Authorization: Bearer <token>
```

OAuth tokens and the `Authorization: token <token>` header form are also
supported.

### Token scopes

Calls to the explicit permissions API require the following access-token
scopes:

- **Reads** (`GetExplicitRepoPermission`, `ListExplicitRepoPermissions`)
  require the `externalapi:read` scope.
- **Writes** (`CreateExplicitRepoPermission`, `DeleteExplicitRepoPermission`)
  require the `externalapi:write` scope.

Broadly-scoped `user:all` tokens are still accepted, but their use against the
Sourcegraph API is recorded in the audit log. We recommend using narrowly
scoped tokens.

### RBAC permissions

In addition to a valid token, the calling user must hold the appropriate RBAC
permission:

- `REPO_PERMISSIONS#READ` for read operations.
- `REPO_PERMISSIONS#WRITE` for write operations.

## Explicit repository permissions operations

The explicit permissions API is served under `/api/` on your Sourcegraph
instance. Requests and responses are JSON, sent over HTTPS using `POST`. The
authoritative schema is published at `/api-reference`; the summary below
documents the operations that are most commonly used.

### Resource names

Resources are identified using [AIP-122 style resource names](https://google.aip.dev/122):

| Resource     | Pattern                                                                  | Example                                              |
| ------------ | ------------------------------------------------------------------------ | ---------------------------------------------------- |
| Repository   | `repositories/{numeric_id}`                                              | `repositories/123`                                   |
| User         | `users/{numeric_id}`, `users/@{username}`, or `users/{email}`            | `users/456`, `users/@alice`, `users/alice@acme.com`  |
| Permission   | `repositories/{repo_id}/explicitRepoPermissions/{user_id_or_identifier}` | `repositories/123/explicitRepoPermissions/@alice`    |

When you create or read a permission, the server returns the canonical form
(`repositories/{repo_id}/explicitRepoPermissions/{numeric_user_id}`), even if
the request used an alias such as `@alice`.

### Operations

| Method                                                            | Purpose                                                               | Required scope      |
| ----------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------- |
| `explicitrepopermissions.v1.Service/GetExplicitRepoPermission`    | Look up whether a specific user has explicit access to a repository.  | `externalapi:read`  |
| `explicitrepopermissions.v1.Service/ListExplicitRepoPermissions`  | List all users with access to a repo, or all repos a user can access. | `externalapi:read`  |
| `explicitrepopermissions.v1.Service/CreateExplicitRepoPermission` | Grant a user explicit access to a repository.                         | `externalapi:write` |
| `explicitrepopermissions.v1.Service/DeleteExplicitRepoPermission` | Revoke a user's explicit access to a repository.                      | `externalapi:write` |

#### `GetExplicitRepoPermission`

Request:

```json
{ "name": "repositories/123/explicitRepoPermissions/@alice" }
```

Response:

```json
{
  "name": "repositories/123/explicitRepoPermissions/456",
  "user": "users/456",
  "repository": "repositories/123"
}
```

#### `ListExplicitRepoPermissions`

Lists explicit permissions under a `parent`, which may be either a repository
or a user. Results are paginated; an empty `next_page_token` means no more
results.

Request — list users with explicit access to a repository:

```json
{ "parent": "repositories/123", "page_size": 50, "page_token": "" }
```

Request — list repositories a user has explicit access to:

```json
{ "parent": "users/@alice", "page_size": 50 }
```

Response:

```json
{
  "explicit_repo_permissions": [
    {
      "name": "repositories/123/explicitRepoPermissions/456",
      "user": "users/456",
      "repository": "repositories/123"
    }
  ],
  "next_page_token": ""
}
```

#### `CreateExplicitRepoPermission`

Grants a user access to a repository. The `parent` can be either side of the
relationship, with the other side specified inside `explicit_repo_permission`.

Request — parent is a repository:

```json
{
  "parent": "repositories/123",
  "explicit_repo_permission": { "user": "users/@alice" }
}
```

Request — parent is a user:

```json
{
  "parent": "users/@alice",
  "explicit_repo_permission": { "repository": "repositories/123" }
}
```

The response is the created `ExplicitRepoPermission` resource.

#### `DeleteExplicitRepoPermission`

Revokes a user's access to a repository.

Request:

```json
{ "name": "repositories/123/explicitRepoPermissions/@alice" }
```

Response:

```json
{}
```

### Examples

The examples below use a placeholder instance at
`https://sourcegraph.example.com` and assume a Sourcegraph access token is
available in the `SRC_ACCESS_TOKEN` environment variable.

#### Grant `alice` access to repository `123`

```bash
curl -X POST \
  -H "Authorization: Bearer $SRC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "parent": "repositories/123",
    "explicit_repo_permission": { "user": "users/@alice" }
  }' \
  https://sourcegraph.example.com/api/explicitrepopermissions.v1.Service/CreateExplicitRepoPermission
```

#### List all users with explicit access to repository `123`

```bash
curl -X POST \
  -H "Authorization: Bearer $SRC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "parent": "repositories/123", "page_size": 50 }' \
  https://sourcegraph.example.com/api/explicitrepopermissions.v1.Service/ListExplicitRepoPermissions
```

To page through more than `page_size` results, pass the `next_page_token`
returned by the previous response as `page_token` in the next request.

#### List all repositories `alice` has explicit access to

```bash
curl -X POST \
  -H "Authorization: Bearer $SRC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "parent": "users/@alice", "page_size": 50 }' \
  https://sourcegraph.example.com/api/explicitrepopermissions.v1.Service/ListExplicitRepoPermissions
```

#### Revoke `alice`'s access to repository `123`

```bash
curl -X POST \
  -H "Authorization: Bearer $SRC_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "repositories/123/explicitRepoPermissions/@alice" }' \
  https://sourcegraph.example.com/api/explicitrepopermissions.v1.Service/DeleteExplicitRepoPermission
```

## Capabilities not yet available in the Sourcegraph API

The following capabilities related to explicit permissions are not yet
exposed through the Sourcegraph API. They are currently available only
through the [Sourcegraph GraphQL debug API](/api/graphql). We plan to port
these capabilities to the Sourcegraph API in a future release; until then,
prefer the Sourcegraph GraphQL debug API for these specific operations.

### Marking a repository as unrestricted

It can occasionally be useful to mark a repository as `unrestricted`, meaning
that it is available to all Sourcegraph users regardless of any explicit or
synced permissions. Setting `unrestricted` back to `false` restores the
previous behaviour.

This capability is currently only available via the
[Sourcegraph GraphQL debug API](/api/graphql).

### Sub-repository permissions (experimental)

Sourcegraph also supports permissions at a per-file or per-directory level
within a repository. This is an **experimental** feature; enable it in the
[site configuration](/admin/config/site-config) with:

```json
"experimentalFeatures": {
    "subRepoPermissions": { "enabled": true }
}
```

Sub-repo rules use [glob syntax](<https://en.wikipedia.org/wiki/Glob_(programming)>);
a `-` prefix denies a path, rules are evaluated in the order they are
specified, and any path that does not match a rule defaults to deny. A user
who has general access to the repository but has no sub-repo rules set is
granted access to the entire repository contents.

Setting sub-repository permissions is currently only available via the
[Sourcegraph GraphQL debug API](/api/graphql).
