mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-03 05:10:16 +03:00
# Description of Changes Multiple named **personal** API keys per user, replacing the single opaque per-user key. - Create (name + one-time secret), list, and revoke named keys from the portal Infrastructure → API Keys tab. Works self-hosted and SaaS (`X-API-KEY`). - Per-key usage stats (today / trailing 30 days / lifetime); API-processed documents are attributed to the specific key in the processor's Documents feed. - The legacy single per-user key keeps working and is lazily represented as a named key. Rotating it revokes its migrated shadow row so the old secret stops authenticating. - Per-user (not per-key) rate limiting plus a per-user active-key cap, so minting keys can't multiply the daily quota. Name-length cap; race-safe migration and usage recording. Keys are strictly personal: one owner, full access, no sharing. Team-shared / scoped keys and per-key access levels were intentionally left out of this PR to keep it small and easy to review; they can follow as a separate, focused change. > Note: the screenshots from the original revision showed an earlier team-scoped design and need refreshing. --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [x] I have run `task check` to verify linters, typechecks, and tests pass - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing) for more details. --------- Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
87 lines
4.0 KiB
Gherkin
87 lines
4.0 KiB
Gherkin
@jwt @auth @apikey
|
|
Feature: API Keys management API
|
|
|
|
Tests for the portal API-keys REST API, which lets a user mint, list, and
|
|
revoke named personal API keys.
|
|
|
|
Endpoints (all @EnterpriseEndpoint, JWT/ROLE required):
|
|
- GET /api/v1/proprietary/ui-data/infrastructure/api-keys (list)
|
|
- POST /api/v1/proprietary/ui-data/infrastructure/api-keys (create)
|
|
- DELETE /api/v1/proprietary/ui-data/infrastructure/api-keys/{id} (revoke)
|
|
|
|
Because these are @EnterpriseEndpoint, authenticated responses may be 200
|
|
(enterprise enabled) or 403 (feature not in this build). Unauthenticated
|
|
requests must always be rejected with 401.
|
|
|
|
The legacy single per-user key (the global API key) must keep working so no
|
|
key created before multi-key support is ever lost.
|
|
|
|
Admin credentials: username=admin, password=stirling
|
|
Global API key: 123456789
|
|
|
|
# =========================================================================
|
|
# LIST
|
|
# =========================================================================
|
|
|
|
@positive
|
|
Scenario: Admin can list API keys
|
|
Given I am logged in as admin
|
|
When I send a GET request to "/api/v1/proprietary/ui-data/infrastructure/api-keys" with JWT authentication
|
|
Then the response status code should be one of "200, 403"
|
|
|
|
@negative
|
|
Scenario: Unauthenticated list request returns 401
|
|
When I send a GET request to "/api/v1/proprietary/ui-data/infrastructure/api-keys" with no authentication
|
|
Then the response status code should be 401
|
|
|
|
# =========================================================================
|
|
# CREATE
|
|
# =========================================================================
|
|
|
|
@positive
|
|
Scenario: Admin can create a personal API key
|
|
Given I am logged in as admin
|
|
When I send a JSON POST request to "/api/v1/proprietary/ui-data/infrastructure/api-keys" with JWT authentication and body '{"name": "bdd_personal_key"}'
|
|
Then the response status code should be one of "200, 403"
|
|
|
|
@negative
|
|
Scenario: Creating a key without a name is rejected
|
|
Given I am logged in as admin
|
|
When I send a JSON POST request to "/api/v1/proprietary/ui-data/infrastructure/api-keys" with JWT authentication and body '{"name": ""}'
|
|
Then the response status code should be one of "400, 403"
|
|
|
|
@negative
|
|
Scenario: Unauthenticated create request returns 401
|
|
When I send a POST request to "/api/v1/proprietary/ui-data/infrastructure/api-keys" with no authentication
|
|
Then the response status code should be 401
|
|
|
|
# =========================================================================
|
|
# REVOKE
|
|
# =========================================================================
|
|
|
|
@negative
|
|
Scenario: Unauthenticated revoke request returns 401
|
|
When I send a DELETE request to "/api/v1/proprietary/ui-data/infrastructure/api-keys/1" with no authentication
|
|
Then the response status code should be 401
|
|
|
|
@positive
|
|
Scenario: Admin revoking a non-existent key is handled, not a bypass
|
|
Given I am logged in as admin
|
|
When I send a DELETE request to "/api/v1/proprietary/ui-data/infrastructure/api-keys/999999" with JWT authentication
|
|
Then the response status code should be one of "204, 403, 404"
|
|
|
|
# =========================================================================
|
|
# LEGACY KEY BACKWARD COMPATIBILITY
|
|
# =========================================================================
|
|
|
|
@positive
|
|
Scenario: The legacy global API key still authenticates
|
|
When I send a GET request to "/api/v1/auth/me" with API key "123456789"
|
|
Then the response status code should be 200
|
|
And the response JSON should have field "username"
|
|
|
|
@negative
|
|
Scenario: An unknown API key is rejected
|
|
When I send a GET request to "/api/v1/auth/me" with API key "not-a-real-api-key-000"
|
|
Then the response status code should be 401
|