<!-- Raise an issue to propose your change
(https://github.com/cvat-ai/cvat/issues).
It helps to avoid duplication of efforts from multiple independent
contributors.
Discuss your ideas with maintainers to be sure that changes will be
approved and merged.
Read the [Contribution guide](https://docs.cvat.ai/docs/contributing/).
-->
<!-- Provide a general summary of your changes in the Title above -->
### Motivation and context
This PR adds file-based profile creation:
- `cvat-cli profile create --file <path>`
- Supports plain-text PAT files
- Supports JSON envelopes with `token`, optional `server`, and optional
`name`
- Explicit `--name` and `--server-host` override envelope values
- A complete JSON envelope can create a profile without extra CLI
arguments
It also includes:
- Tests for plain-file import, JSON import, and precedence rules
- CLI/SDK/profile documentation updates
- A changelog entry for `--file`
### How has this been tested?
<!-- Please describe in detail how you tested your changes.
Include details of your testing environment, and the tests you ran to
see how your change affects other areas of the code, etc. -->
### Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply.
If an item isn't applicable for some reason, then ~~explicitly
strikethrough~~ the whole
line. If you don't do that, GitHub will show incorrect progress for the
pull request.
If you're unsure about any of these, don't hesitate to ask. We're here
to help! -->
- [x] I submit my changes into the `develop` branch
- [x] I have created a changelog fragment <!-- see top comment in
CHANGELOG.md -->
- [x] I have updated the documentation accordingly
- [x] I have added tests to cover my changes
- [x] I have linked related issues (see [GitHub docs](
https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword))
### License
- [x] I submit _my code changes_ under the same [MIT License](
https://github.com/cvat-ai/cvat/blob/develop/LICENSE) that covers the
project.
Feel free to contact the maintainers if that's a concern.
---------
Co-authored-by: Maxim Zhiltsov <maxim@cvat.ai>
Currently, all source files are located in `/home/django`, and owned by
`django`. This means that if there's any vulnerability that lets an
attacker overwrite files in the server, they can replace source files
with their own code, and potentially get that code executed. That's
pretty bad, so I want to harden against that.
Make all source files owned by root, and move them to `/opt/cvat`. Add a
`manage.py` symlink in `/home/django` for backwards compatibility. It
happens that if a script is a symlink, Python does not add the symlink's
directory to `sys.path`, which is great for us, since that lets us avoid
a writable directory on there.
Still, even though `/home/django/manage.py` is owned by root, an
attacker could potentially be able to delete it and replace it with
their own malicious file. To be a bit more safe, replace `~/manage.py`
calls in backend scripts with `django-admin`.
To make sure CVAT can still find the data directory, add a new
environment variable, `CVAT_BASE_DIR` and set it in the Docker image.
This also fixes a minor bug: we no longer override the `HOME`
environment variable in the `Dockerfile`, so now it's automatically set
by `Docker` depending on the current user.
<!-- Raise an issue to propose your change
(https://github.com/cvat-ai/cvat/issues).
It helps to avoid duplication of efforts from multiple independent
contributors.
Discuss your ideas with maintainers to be sure that changes will be
approved and merged.
Read the [Contribution guide](https://docs.cvat.ai/docs/contributing/).
-->
<!-- Provide a general summary of your changes in the Title above -->
### Motivation and context
This branch completes the CLI workflow for persistent authentication
profiles. Users can save a CVAT server URL and Personal Access Token
under a named profile, then reuse it with `--profile` instead of
repeatedly passing credentials on the command line.
It adds `cvat-cli profile` commands to:
- List saved profiles, including the active default.
- Create a profile from a PAT, optionally deriving its name from the
server.
- Set, print, or clear the default profile.
- Delete profiles safely.
The implementation builds on the auth/config resolution already present
in `develop`. It uses the SDK’s `AuthStore.put_profile` API, preserves
copy-on-write store updates, and applies the same server-port validation
used by normal CLI client creation.
URL normalization was also moved into shared SDK utilities so both
`Client` and profile creation use one implementation for default HTTPS
schemes, trailing-slash removal, and invalid-scheme validation.
### How has this been tested?
<!-- Please describe in detail how you tested your changes.
Include details of your testing environment, and the tests you ran to
see how your change affects other areas of the code, etc. -->
### Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply.
If an item isn't applicable for some reason, then ~~explicitly
strikethrough~~ the whole
line. If you don't do that, GitHub will show incorrect progress for the
pull request.
If you're unsure about any of these, don't hesitate to ask. We're here
to help! -->
- [x] I submit my changes into the `develop` branch
- [x] I have created a changelog fragment <!-- see top comment in
CHANGELOG.md -->
- [ ] I have updated the documentation accordingly
- [x] I have added tests to cover my changes
- [x] I have linked related issues (see [GitHub docs](
https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword))
### License
- [x] I submit _my code changes_ under the same [MIT License](
https://github.com/cvat-ai/cvat/blob/develop/LICENSE) that covers the
project.
Feel free to contact the maintainers if that's a concern.
---------
Co-authored-by: Maxim Zhiltsov <maxim@cvat.ai>
<!-- Raise an issue to propose your change
(https://github.com/cvat-ai/cvat/issues).
It helps to avoid duplication of efforts from multiple independent
contributors.
Discuss your ideas with maintainers to be sure that changes will be
approved and merged.
Read the [Contribution guide](https://docs.cvat.ai/docs/contributing/).
-->
<!-- Provide a general summary of your changes in the Title above -->
### Motivation and context
This branch continues the persistent authentication work for the CVAT
SDK and CLI. It makes saved auth profiles usable from CLI workflows, so
users do not need to repeatedly pass `--server-host`, `--server-port`,
and `--auth` for every command.
The changes centralize CLI auth resolution around the SDK auth helpers,
add support for profile/default-server based connection selection, and
introduce `cvat-cli config default-server` for managing the fallback
server used outside profile-based flows. The branch also adds dispatch
support for CLI commands that do not need an authenticated client, plus
tests and changelog coverage for the new config command and auth
behavior.
### How has this been tested?
Automated and manual tests
### Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply.
If an item isn't applicable for some reason, then ~~explicitly
strikethrough~~ the whole
line. If you don't do that, GitHub will show incorrect progress for the
pull request.
If you're unsure about any of these, don't hesitate to ask. We're here
to help! -->
- [x] I submit my changes into the `develop` branch
- [x] I have created a changelog fragment <!-- see top comment in
CHANGELOG.md -->
- [ ] I have updated the documentation accordingly
- [x] I have added tests to cover my changes
- [x] I have linked related issues (see [GitHub docs](
https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword))
### License
- [x] I submit _my code changes_ under the same [MIT License](
https://github.com/cvat-ai/cvat/blob/develop/LICENSE) that covers the
project.
Feel free to contact the maintainers if that's a concern.
---------
Co-authored-by: Maxim Zhiltsov <maxim@cvat.ai>
<!-- Raise an issue to propose your change
(https://github.com/cvat-ai/cvat/issues).
It helps to avoid duplication of efforts from multiple independent
contributors.
Discuss your ideas with maintainers to be sure that changes will be
approved and merged.
Read the [Contribution guide](https://docs.cvat.ai/docs/contributing/).
-->
<!-- Provide a general summary of your changes in the Title above -->
### Motivation and context
<!-- Why is this change required? What problem does it solve? If it
fixes an open
issue, please link to the issue here. Describe your changes in detail,
add
screenshots. -->
### How has this been tested?
<!-- Please describe in detail how you tested your changes.
Include details of your testing environment, and the tests you ran to
see how your change affects other areas of the code, etc. -->
### Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply.
If an item isn't applicable for some reason, then ~~explicitly
strikethrough~~ the whole
line. If you don't do that, GitHub will show incorrect progress for the
pull request.
If you're unsure about any of these, don't hesitate to ask. We're here
to help! -->
- [x] I submit my changes into the `develop` branch
- [ ] I have created a changelog fragment <!-- see top comment in
CHANGELOG.md -->
- [ ] I have updated the documentation accordingly
- [x] I have added tests to cover my changes
- [x] I have linked related issues (see [GitHub docs](
https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword))
### License
- [x] I submit _my code changes_ under the same [MIT License](
https://github.com/cvat-ai/cvat/blob/develop/LICENSE) that covers the
project.
Feel free to contact the maintainers if that's a concern.
<!-- Raise an issue to propose your change
(https://github.com/cvat-ai/cvat/issues).
It helps to avoid duplication of efforts from multiple independent
contributors.
Discuss your ideas with maintainers to be sure that changes will be
approved and merged.
Read the [Contribution guide](https://docs.cvat.ai/docs/contributing/).
-->
<!-- Provide a general summary of your changes in the Title above -->
### Motivation and context
<!-- Why is this change required? What problem does it solve? If it
fixes an open
issue, please link to the issue here. Describe your changes in detail,
add
screenshots. -->
### How has this been tested?
<!-- Please describe in detail how you tested your changes.
Include details of your testing environment, and the tests you ran to
see how your change affects other areas of the code, etc. -->
### Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply.
If an item isn't applicable for some reason, then ~~explicitly
strikethrough~~ the whole
line. If you don't do that, GitHub will show incorrect progress for the
pull request.
If you're unsure about any of these, don't hesitate to ask. We're here
to help! -->
- [x] I submit my changes into the `develop` branch
- [x] I have created a changelog fragment <!-- see top comment in
CHANGELOG.md -->
- [ ] I have updated the documentation accordingly
- [x] I have added tests to cover my changes
- [x] I have linked related issues (see [GitHub docs](
https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword))
### License
- [x] I submit _my code changes_ under the same [MIT License](
https://github.com/cvat-ai/cvat/blob/develop/LICENSE) that covers the
project.
Feel free to contact the maintainers if that's a concern.
---------
Co-authored-by: Maxim Zhiltsov <maxim@cvat.ai>
<!-- Raise an issue to propose your change
(https://github.com/cvat-ai/cvat/issues).
It helps to avoid duplication of efforts from multiple independent
contributors.
Discuss your ideas with maintainers to be sure that changes will be
approved and merged.
Read the [Contribution guide](https://docs.cvat.ai/docs/contributing/).
-->
<!-- Provide a general summary of your changes in the Title above -->
### Motivation and context
Implemented all necessary `AuthStore` methods including:
* `list_profiles() -> dict[str, ProfileEntry]`
* `get_profile(name: str) -> ProfileEntry | None`
* `add_profile(name: str, entry: ProfileEntry, *, set_default: bool =
False) -> None`
* `remove_profile(name: str) -> None` — raises KeyError if absent;
clears default_profile if it pointed here.
* `get_default_profile() -> tuple[str, ProfileEntry] | None`
* `set_default_profile(name: str) -> None — raises KeyError if the name
is not a saved profile.`
* `clear_default_profile() -> None`
* `get_default_server() -> str | None`
* `set_default_server(server: str) -> None`
* `clear_default_server() -> None`
### How has this been tested?
Added automated tests
### Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply.
If an item isn't applicable for some reason, then ~~explicitly
strikethrough~~ the whole
line. If you don't do that, GitHub will show incorrect progress for the
pull request.
If you're unsure about any of these, don't hesitate to ask. We're here
to help! -->
- [x] I submit my changes into the `develop` branch
- [x] I have created a changelog fragment <!-- see top comment in
CHANGELOG.md -->
- [ ] I have updated the documentation accordingly
- [x] I have added tests to cover my changes
- [x] I have linked related issues (see [GitHub docs](
https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword))
### License
- [x] I submit _my code changes_ under the same [MIT License](
https://github.com/cvat-ai/cvat/blob/develop/LICENSE) that covers the
project.
Feel free to contact the maintainers if that's a concern.
---------
Co-authored-by: Maxim Zhiltsov <maxim@cvat.ai>
### Motivation and context
#### Fix UnboundLocalError on GET /api/tasks/<id>/data/meta for tasks
without media
#### Motivation
Production is throwing 500s on GET /api/tasks/<id>/data/meta:
```python
UnboundLocalError: cannot access local variable 'media' where it is not associated with a value
File "cvat/apps/engine/views.py", line 1935, in metadata
for item in media
```
#### Root cause
TaskViewSet.metadata() dispatches on db_task.media_type through an if /
elif / elif chain:
```python
if db_task.media_type == AUDIO and mode == INTERPOLATION:
media = [db_data.audio]; chapters = None; def serialize_media_item(...)
elif db_task.media_type in (IMAGE, POINT_CLOUD):
media = ...; chapters = ...
elif db_task.media_type: # ← truthiness guard
assert False, f"Unknown media type '{db_task.media_type}'"
# no else
```
Task.media_type is declared CharField(..., default="", blank=True), so a
freshly-created Task whose Data row exists but whose media has not been
populated yet has media_type == "". That value is falsy, so none of the
branches execute and media, chapters, and serialize_media_item are never
bound. The subsequent for item in media raises UnboundLocalError and DRF
returns a 500.
The empty-media state was already known at the top of the same method —
the prefetch() match block explicitly handles ("", "") as a no-op — but
that handling was never carried through to the body of the view. The
regression was introduced when the audio media type was added
https://github.com/cvat-ai/cvat/pull/10551, which restructured the
previous if/else into the current chain and put a truthy guard on the
final branch.
#### Fix
Raise ValidationError early, mirroring the neighbouring db_data is None
check just a few lines above:
```python
db_data = db_task.data
if db_data is None:
raise ValidationError("Data is not uploaded for the task yet")
if not db_task.media_type:
raise ValidationError("Task has no media data yet")
```
This turns the silent 500 into an actionable 400 with a clear message, is consistent with the existing "data not uploaded" pattern, and requires no changes to the dispatch chain below.
### How has this been tested?
<!-- Please describe in detail how you tested your changes.
Include details of your testing environment, and the tests you ran to
see how your change affects other areas of the code, etc. -->
### Checklist
<!-- Go over all the following points, and put an `x` in all the boxes that apply.
If an item isn't applicable for some reason, then ~~explicitly strikethrough~~ the whole
line. If you don't do that, GitHub will show incorrect progress for the pull request.
If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [x] I submit my changes into the `develop` branch
- [x] I have created a changelog fragment <!-- see top comment in CHANGELOG.md -->
- [x] I have updated the documentation accordingly
- [x] I have added tests to cover my changes
- [x] I have linked related issues (see [GitHub docs](
https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword))
### License
- [x] I submit _my code changes_ under the same [MIT License](
https://github.com/cvat-ai/cvat/blob/develop/LICENSE) that covers the project.
Feel free to contact the maintainers if that's a concern.
---------
Co-authored-by: Maxim Zhiltsov <maxim@cvat.ai>
Our Helm tests currently use the default Python version in
`ubuntu-latest`, which will become 3.14 once `ubuntu-latest` becomes
Ubuntu 26.04. We should make sure the tests are ready for that.
Some notes:
* The `numba` pin should not be necessary anymore, since the problem it
works around was fixed in coverage 7.6.1, and I've already updated
coverage to 7.14.0 in 76e15a01e0.
* There is no version of NumPy that supports both 3.10 and 3.14. I've
elected to use the lowest version that supports each, since it helps
ensure that we didn't make the SDK dependent on a newer version by
accident.
* pytest 9.0.3 is not the latest version, but the newest one is
currently incompatible with pytest-cases.
Co-authored-by: Maxim Zhiltsov <zhiltsov.max35@gmail.com>
Extend ModelListMixin.list() to accept arbitrary query parameters
(filter, search, ordering, field filters, etc.) and forward them to the
paginated list endpoint. The `filter` argument additionally accepts a
JsonLogic mapping which is serialized to JSON automatically.
---------
Co-authored-by: Maxim Zhiltsov <maxim@cvat.ai>
Currently this either returns 200 and an empty list (if the parent
quality report is in an accessible organization or a personal
workspace), or 500 (if the parent is in an inaccessible organization).
This is inconsistent with all other resource-based filters, where the
endpoint returns 403 if the resource is inaccessible (and obviously we
should never return a 500 status regardless). It's also a (very minor)
security problem, since it lets an attacker learn some information about
a quality report they can't access.
The cause is that we don't explicitly check that the user has
permissions to view the parent, so do that.
Thanks to @geo-chen for the report.
Fixes#8914
**Issue**: Several high-level SDK methods — `Project.get_tasks()`,
`Project.get_labels()`, `Task.get_jobs()`, `Task.get_labels()`,
`Job.get_issues()`, `Job.get_labels()`, and `Issue.get_comments()` —
failed with IAM
permission errors when called on resources belonging to an organization,
unless the client had already been configured with the correct
organization context via `client.organization_context()`.
**Root cause**: These methods issued API requests without propagating
the organization scope inferred from the resource itself, so CVAT's IAM
layer rejected them as if they were personal workspace requests.
**Fix**: Added a `organization_context_for(client, organization_id)`
context manager in `model_proxy.py`. It looks up the organization from
the resource's organization field and temporarily sets the matching org
slug on the client (skipping the switch if the slug is already correct).
All affected proxy methods now wrap their API calls with this context
manager, so the organization scope is automatically applied regardless
of how the client was initialized.
Tests covering all affected methods with org-owned resources were added
to verify the fix.
<!-- Raise an issue to propose your change
(https://github.com/cvat-ai/cvat/issues).
It helps to avoid duplication of efforts from multiple independent
contributors.
Discuss your ideas with maintainers to be sure that changes will be
approved and merged.
Read the [Contribution guide](https://docs.cvat.ai/docs/contributing/).
-->
<!-- Provide a general summary of your changes in the Title above -->
### Motivation and context
**Problem Statement:**
Before these changes, when the agent receives a task annotation request,
it first downloads all the images (in chunks), then iterates through
them and runs the model on each one. But it's not the best behavior for
the agent: it means the agent needs enough disk space to store all the
images (even though they're not all in use at the same time); moreover,
the progress bar in the UI hangs at zero for a long time, which isn't
very informative.
Now it works like this: the agent downloads the first chunk, then
immediately processes it. While it's processing, the agent downloads the
next chunk. After processing, the chunk is deleted.
### How has this been tested?
Manual and automated tests.
### Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply.
If an item isn't applicable for some reason, then ~~explicitly
strikethrough~~ the whole
line. If you don't do that, GitHub will show incorrect progress for the
pull request.
If you're unsure about any of these, don't hesitate to ask. We're here
to help! -->
- [x] I submit my changes into the `develop` branch
- [x] I have created a changelog fragment <!-- see top comment in
CHANGELOG.md -->
- [x] I have updated the documentation accordingly
- [x] I have added tests to cover my changes
- [x] I have linked related issues (see [GitHub docs](
https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword))
### License
- [x] I submit _my code changes_ under the same [MIT License](
https://github.com/cvat-ai/cvat/blob/develop/LICENSE) that covers the
project.
Feel free to contact the maintainers if that's a concern.
---------
Co-authored-by: Roman Donchenko <roman@cvat.ai>
There are actually two problems with it:
* The fixtures could execute in the wrong order, because all of the
fixtures in this test are class-level, and the order pytest executes
these in is indeterminate. So the DB/Redis reset could happen after the
creation of test data. Fix it by adding explicit fixture dependencies.
* It takes a while for all the setup to execute, which can time out.
Bump the timeout.
In addition, update the `wait_background_request` function to stop
waiting if a request fails. This lets the test fail early if something
goes wrong, instead of timing out.