---
url: "https://vueda.dev/v3/reference/api/py/vueda.core.permissions/BaseRowLevelPermissions.md"
title: "BaseRowLevelPermissions"
---

# BaseRowLevelPermissions

## Overview

Base class for row-level permission checks. Subclass this on a model's inner
``RowLevelPermissions`` class to restrict which rows a user can read, modify, or delete.

All methods return ``None`` by default (no opinion). Return ``True`` to grant, ``False``
to deny, or a ``Q`` object (queryset methods) to filter rows.

## `check_instance` {#check_instance}

True if the user has the permission, False if the user does not have the permission, None if the check is not
applicable due to there being no row level permissions for the model.

### Signature {#check_instance-signature}

`check_instance(cls, model, obj, perm, user, perm_type)`

#### Parameters {#check_instance-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| cls |  | yes |  |  |
| <span id="check_instance-param-model">model</span> |  | yes |  |  |
| <span id="check_instance-param-obj">obj</span> |  | yes |  |  |
| <span id="check_instance-param-perm">perm</span> |  | yes |  |  |
| <span id="check_instance-param-user">user</span> |  | yes |  |  |
| <span id="check_instance-param-perm_type">perm_type</span> |  | yes |  |  |

#### Returns {#check_instance-returns}

`bool | None`

### Source {#check_instance-source}

`server/vueda/core/permissions.py:303`

## `check_instance_workflow` {#check_instance_workflow}

Row-level check that is workflow-aware. Only called when the object is under workflow.
Receives grant_or_deny (None/True/False) from state permission resolution.
Runs AFTER check_instance and can override any prior decision, including state deny.

### Signature {#check_instance_workflow-signature}

`check_instance_workflow(cls, model, obj, perm, user, perm_type, grant_or_deny)`

#### Parameters {#check_instance_workflow-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| cls |  | yes |  |  |
| <span id="check_instance_workflow-param-model">model</span> |  | yes |  |  |
| <span id="check_instance_workflow-param-obj">obj</span> |  | yes |  |  |
| <span id="check_instance_workflow-param-perm">perm</span> |  | yes |  |  |
| <span id="check_instance_workflow-param-user">user</span> |  | yes |  |  |
| <span id="check_instance_workflow-param-perm_type">perm_type</span> |  | yes |  |  |
| <span id="check_instance_workflow-param-grant_or_deny">grant_or_deny</span> |  | yes |  |  |

#### Returns {#check_instance_workflow-returns}

`bool | None`

### Source {#check_instance_workflow-source}

`server/vueda/core/permissions.py:327`

## `check_queryset` {#check_queryset}

Return of None means do not filter based on row level permissions.
Return of True means the user has the permission without needing to check the rows.
Return of False means the user does not have the permission, and we can stop checking.
Return of Q means we need to filter the rows based on the row level permissions.

### Signature {#check_queryset-signature}

`check_queryset(cls, queryset, perm, user, perm_type)`

#### Parameters {#check_queryset-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| cls |  | yes |  |  |
| <span id="check_queryset-param-queryset">queryset</span> |  | yes |  |  |
| <span id="check_queryset-param-perm">perm</span> |  | yes |  |  |
| <span id="check_queryset-param-user">user</span> |  | yes |  |  |
| <span id="check_queryset-param-perm_type">perm_type</span> |  | yes |  |  |

#### Returns {#check_queryset-returns}

`django.db.models.query_utils.Q | bool | None`

### Source {#check_queryset-source}

`server/vueda/core/permissions.py:314`

## `check_queryset_workflow` {#check_queryset_workflow}

Queryset-level filter that is workflow-aware. Only called when the model is under workflow.
The queryset is pre-annotated with state permission info.
Use F(state_denied_annotation) / F(state_granted_annotation) in Q expressions.

Returns:
    None  - no workflow-specific opinion, preserve prior filtering
    Q     - ANDed with the current queryset
    True  - no additional restriction
    False - empty queryset

### Signature {#check_queryset_workflow-signature}

`check_queryset_workflow(cls, queryset, perm, user, perm_type, state_denied_annotation, state_granted_annotation)`

#### Parameters {#check_queryset_workflow-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| cls |  | yes |  |  |
| <span id="check_queryset_workflow-param-queryset">queryset</span> |  | yes |  |  |
| <span id="check_queryset_workflow-param-perm">perm</span> |  | yes |  |  |
| <span id="check_queryset_workflow-param-user">user</span> |  | yes |  |  |
| <span id="check_queryset_workflow-param-perm_type">perm_type</span> |  | yes |  |  |
| <span id="check_queryset_workflow-param-state_denied_annotation">state_denied_annotation</span> |  | yes |  |  |
| <span id="check_queryset_workflow-param-state_granted_annotation">state_granted_annotation</span> |  | yes |  |  |

#### Returns {#check_queryset_workflow-returns}

`django.db.models.query_utils.Q | bool | None`

### Source {#check_queryset_workflow-source}

`server/vueda/core/permissions.py:338`

## Source

`server/vueda/core/permissions.py:294`
