Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
A
aisbf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexlab
aisbf
Commits
d39326be
Commit
d39326be
authored
Apr 20, 2026
by
Your Name
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
0.99.36
parent
1c25697e
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
243 additions
and
416 deletions
+243
-416
ENDPOINTS.md
ENDPOINTS.md
+224
-0
__init__.py
aisbf/__init__.py
+1
-1
main.py
main.py
+10
-413
pyproject.toml
pyproject.toml
+1
-1
setup.py
setup.py
+1
-1
providers.html
templates/dashboard/providers.html
+3
-0
user_providers.html
templates/dashboard/user_providers.html
+3
-0
No files found.
ENDPOINTS.md
0 → 100644
View file @
d39326be
# AISBF Endpoint Documentation
Generated: 2026-04-20T20:48:14+02:00
---
## Access Level Definitions
| Level | Definition |
|-------|------------|
|
**Public**
| No authentication required |
|
**Database user**
| User from the database, both role admin or user |
|
**user**
| User from database with role user |
|
**admin**
| User from database with role admin |
|
**global admin**
| Admin user defined in the
`aisbf.json`
configuration file |
|
**global token**
| Tokens created by the global admin to access the global API |
|
**user token**
| Tokens created by and belonging to a specific database user |
---
## Dashboard Endpoints (UI Access)
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/dashboard`
| GET | Database user | Main dashboard index |
|
`/dashboard/login`
| GET, POST | Public | Login page |
|
`/dashboard/logout`
| GET | Database user | Logout user |
|
`/dashboard/signup`
| GET, POST | Public (if enabled) | User registration |
|
`/dashboard/forgot-password`
| GET, POST | Public | Password reset request |
|
`/dashboard/reset-password`
| GET, POST | Public | Password reset form |
|
`/dashboard/verify`
| GET | Public | Email verification |
|
`/dashboard/verify-email`
| GET | Database user | Resend verification email |
|
`/dashboard/change-password`
| GET, POST | Database user | Change password |
|
`/dashboard/change-email`
| GET, POST | Database user | Change email address |
|
`/dashboard/delete-account`
| GET, POST | Database user | Delete user account |
|
`/dashboard/profile`
| GET, POST | Database user | User profile management |
|
`/dashboard/settings`
| GET, POST | Database user | User settings |
|
`/dashboard/docs`
| GET | Database user | API documentation |
|
`/dashboard/license`
| GET | Database user | License information |
|
`/dashboard/about`
| GET | Database user | About page |
|
`/dashboard/extension/download`
| GET | Database user | Browser extension download |
### Configuration Pages
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/dashboard/providers`
| GET, POST | Database user / Global admin | Provider configuration (auto detects context) |
|
`/dashboard/rotations`
| GET, POST | Database user / Global admin | Rotation configuration (auto detects context) |
|
`/dashboard/autoselect`
| GET, POST | Database user / Global admin | Autoselect configuration (auto detects context) |
|
`/dashboard/providers/get-models`
| POST | Database user / Global admin | Fetch models from provider API |
|
`/dashboard/providers/{name}/upload`
| POST | Database user / Global admin | Upload provider auth files |
|
`/dashboard/providers/{name}/files`
| GET | Database user / Global admin | List provider auth files |
|
`/dashboard/providers/{name}/files/{file}/download`
| GET | Database user / Global admin | Download provider auth file |
|
`/dashboard/providers/{name}/auth/check`
| GET | Database user / Global admin | Check provider OAuth status |
|
`/dashboard/providers/upload-auth-file`
| POST | Database user / Global admin | Chunked file upload for provider credentials |
|
`/dashboard/providers/upload-auth-file/chunk`
| POST | Database user / Global admin | Chunked file upload continuation |
|
`/dashboard/user/tokens`
| GET, POST, DELETE | Database user | API token management |
### Billing & Subscriptions
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/dashboard/pricing`
| GET | Public | Pricing plans page |
|
`/dashboard/subscription`
| GET | Database user | Current subscription status |
|
`/dashboard/billing`
| GET | Database user | Billing history and payment methods |
|
`/dashboard/billing/add-method`
| GET, POST | Database user | Add payment method |
|
`/dashboard/billing/add-method/paypal/oauth`
| GET, POST | Database user | PayPal OAuth initiation |
|
`/dashboard/billing/add-method/paypal/callback`
| GET, POST | Database user | PayPal OAuth callback |
|
`/dashboard/billing/payment-methods/{id}/set-default`
| POST | Database user | Set default payment method |
### Database Admin (Role=admin)
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/dashboard/users`
| GET, POST | admin | User management |
|
`/dashboard/users/add`
| POST | admin | Create new user |
|
`/dashboard/users/{id}/edit`
| POST | admin | Edit user |
|
`/dashboard/users/{id}/delete`
| POST | admin | Delete user |
|
`/dashboard/users/{id}/toggle`
| POST | admin | Toggle user active status |
|
`/dashboard/users/{id}/tier`
| POST | admin | Update user tier |
|
`/dashboard/users/bulk`
| POST | admin | Bulk user operations |
|
`/dashboard/analytics`
| GET | admin | Analytics dashboard |
### Global Admin (aisbf.json defined)
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/dashboard/admin/tiers`
| GET | global admin | Pricing tiers management |
|
`/dashboard/admin/tiers/create`
| GET | global admin | Create new tier |
|
`/dashboard/admin/tiers/edit/{id}`
| GET | global admin | Edit existing tier |
|
`/dashboard/admin/tiers/save`
| POST | global admin | Save tier changes |
|
`/dashboard/admin/payment-settings`
| GET | global admin | Payment system configuration |
|
`/dashboard/response-cache/stats`
| GET | global admin | Cache statistics |
|
`/dashboard/response-cache/clear`
| POST | global admin | Clear cache |
|
`/dashboard/rate-limits`
| GET | global admin | Rate limits dashboard |
|
`/dashboard/rate-limits/data`
| GET | global admin | Rate limits data API |
|
`/dashboard/rate-limits/{provider}/reset`
| POST | global admin | Reset provider rate limits |
|
`/dashboard/condensation`
| GET, POST | global admin | Condensation settings |
|
`/dashboard/restart`
| POST | global admin | Restart server |
|
`/dashboard/test-smtp`
| POST | global admin | Test email configuration |
### OAuth2 Authentication
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/dashboard/claude/auth/start`
| POST | Database user / Global admin | Start Claude OAuth flow |
|
`/dashboard/claude/auth/complete`
| POST | Database user / Global admin | Complete Claude OAuth flow |
|
`/dashboard/claude/auth/callback-status`
| GET | Database user / Global admin | Check OAuth callback status |
|
`/dashboard/kilo/auth/start`
| POST | Database user / Global admin | Start Kilo OAuth flow |
|
`/dashboard/kilo/auth/poll`
| POST | Database user / Global admin | Poll Kilo OAuth status |
|
`/dashboard/kilo/auth/status`
| POST | Database user / Global admin | Kilo auth status |
|
`/dashboard/qwen/auth/start`
| POST | Database user / Global admin | Start Qwen OAuth flow |
|
`/dashboard/qwen/auth/poll`
| POST | Database user / Global admin | Poll Qwen OAuth status |
|
`/dashboard/qwen/auth/status`
| POST | Database user / Global admin | Qwen auth status |
|
`/dashboard/codex/auth/start`
| POST | Database user / Global admin | Start Codex OAuth flow |
|
`/dashboard/codex/auth/poll`
| POST | Database user / Global admin | Poll Codex OAuth status |
|
`/dashboard/codex/auth/status`
| POST | Database user / Global admin | Codex auth status |
|
`/dashboard/codex/auth/logout`
| POST | Database user / Global admin | Codex auth logout |
|
`/dashboard/kilo/auth/logout`
| POST | Database user / Global admin | Kilo auth logout |
|
`/dashboard/qwen/auth/logout`
| POST | Database user / Global admin | Qwen auth logout |
---
## API Endpoints (Programmatic Access)
### Public API
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/api/v1/models`
| GET | Public | List available models |
|
`/api/webhooks/stripe`
| POST | Public (signed) | Stripe webhook endpoint |
|
`/api/webhooks/paypal`
| POST | Public (signed) | PayPal webhook endpoint |
### Global Token / Global Admin
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/api/v1/chat/completions`
| POST | global token | OpenAI-compatible chat completions (global) |
|
`/api/v1/completions`
| POST | global token | Legacy completions endpoint (global) |
|
`/api/v1/embeddings`
| POST | global token | Embeddings generation (global) |
|
`/api/v1/images/generations`
| POST | global token | Image generation (global) |
|
`/api/v1/audio/transcriptions`
| POST | global token | Audio transcription (global) |
|
`/api/v1/audio/speech`
| POST | global token | Text-to-speech (global) |
|
`/api/chat/completions`
| POST | global token | Alias for
`/api/v1/chat/completions`
(global) |
|
`/api/embeddings`
| POST | global token | Alias for
`/api/v1/embeddings`
(global) |
|
`/api/images/generations`
| POST | global token | Alias for
`/api/v1/images/generations`
(global) |
|
`/api/audio/transcriptions`
| POST | global token | Alias for
`/api/v1/audio/transcriptions`
(global) |
|
`/api/audio/speech`
| POST | global token | Alias for
`/api/v1/audio/speech`
(global) |
|
`/api/providers`
| GET | global token | List global providers |
|
`/api/{provider_id}/models`
| GET | global token | List models for specific global provider |
|
`/api/{provider_id}/chat/completions`
| POST | global token | Direct global provider access |
|
`/api/rotations`
| GET | global token | List global rotations |
|
`/api/rotations/models`
| GET | global token | List global rotation models |
|
`/api/rotations/chat/completions`
| POST | global token | Global rotation completions |
|
`/api/autoselect`
| GET | global token | List global autoselect rules |
|
`/api/autoselect/models`
| GET | global token | List global autoselect models |
|
`/api/autoselect/chat/completions`
| POST | global token | Global autoselect completions |
### User Token / Database User
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/api/u/{username}/models`
| GET | user token | List user's available models |
|
`/api/u/{username}/providers`
| GET | user token | List user's providers |
|
`/api/u/{username}/rotations`
| GET | user token | List user's rotations |
|
`/api/u/{username}/rotations/models`
| GET | user token | List user's rotation models |
|
`/api/u/{username}/autoselects`
| GET | user token | List user's autoselect rules |
|
`/api/u/{username}/autoselects/models`
| GET | user token | List user's autoselect models |
|
`/api/u/{username}/chat/completions`
| POST | user token | User-specific completions |
|
`/api/u/{username}/{config_type}/models`
| GET | user token | User-specific config models |
### Billing API
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/api/subscriptions`
| POST | Database user | Create subscription |
|
`/api/subscriptions/status`
| GET | Database user | Subscription status |
|
`/api/subscriptions/upgrade`
| POST | Database user | Upgrade subscription |
|
`/api/subscriptions/downgrade`
| POST | Database user | Downgrade subscription |
|
`/api/subscriptions/cancel`
| POST | Database user | Cancel subscription |
|
`/api/payment-methods`
| GET | Database user | List payment methods |
|
`/api/payment-methods/stripe`
| POST | Database user | Add Stripe payment method |
|
`/api/payment-methods/paypal/initiate`
| POST | Database user | Initiate PayPal payment method |
|
`/api/payment-methods/paypal/complete`
| POST | Database user | Complete PayPal payment method |
|
`/api/payment-methods/crypto`
| POST | Database user | Add crypto payment method |
### Global Admin API
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/api/admin/tiers`
| GET, POST | global admin | Pricing tiers management |
|
`/api/admin/tiers/{id}`
| GET, PUT, DELETE | global admin | Tier CRUD operations |
|
`/api/admin/config/consolidation`
| GET, POST | global admin | Consolidation configuration |
|
`/api/admin/config/email`
| GET, POST | global admin | Email configuration |
|
`/api/admin/config/price-sources`
| GET, POST | global admin | Price sources configuration |
|
`/api/admin/settings/currency`
| GET, POST | global admin | Currency settings |
|
`/api/admin/settings/encryption-key`
| GET, POST | global admin | Encryption key settings |
|
`/api/admin/settings/payment-gateways`
| GET, POST | global admin | Payment gateways settings |
|
`/api/admin/scheduler/status`
| GET | global admin | Scheduler status |
|
`/api/admin/scheduler/run-job`
| POST | global admin | Run scheduler job manually |
|
`/api/admin/payment-system/config`
| GET | global admin | Payment system configuration |
|
`/api/admin/payment-system/status`
| GET | global admin | Payment system status |
|
`/api/admin/crypto/prices`
| GET | global admin | Crypto prices |
|
`/api/admin/crypto/btc-prices`
| GET | global admin | BTC prices |
|
`/api/users/search`
| GET | admin | Search users |
### Legacy/Deprecated Endpoints
| Endpoint | Methods | Access Level | Description |
|----------|---------|--------------|-------------|
|
`/api/autoselections/models`
| GET | global token | Deprecated alias for
`/api/autoselect/models`
|
|
`/api/u/{username}/autoselections/models`
| GET | user token | Deprecated alias for
`/api/u/{username}/autoselects/models`
|
|
`/api/proxy/{content_id}`
| GET | Database user | Content proxy endpoint |
---
## Special Auto-Context Endpoints
Endpoints marked with
`Database user / Global admin`
automatically detect context:
-
If accessed by
`global admin`
→ operates on global JSON configuration
-
If accessed by
`Database user`
→ operates on user-specific database configuration
-
No separate endpoints needed for global vs user configuration
All endpoints enforce proper authentication and authorization checks before processing requests.
aisbf/__init__.py
View file @
d39326be
...
...
@@ -54,7 +54,7 @@ from .auth.qwen import QwenOAuth2
from
.handlers
import
RequestHandler
,
RotationHandler
,
AutoselectHandler
from
.utils
import
count_messages_tokens
,
split_messages_into_chunks
,
get_max_request_tokens_for_model
__version__
=
"0.99.3
5
"
__version__
=
"0.99.3
6
"
__all__
=
[
# Config
"config"
,
...
...
main.py
View file @
d39326be
...
...
@@ -5570,239 +5570,6 @@ async def dashboard_restart(request: Request):
return
JSONResponse
({
"error"
:
f
"Failed to reload configuration: {str(e)}"
},
status_code
=
500
)
# User-specific configuration management routes
@
app
.
get
(
"/dashboard/user/providers"
,
response_class
=
HTMLResponse
)
async
def
dashboard_user_providers
(
request
:
Request
):
"""User provider management page"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/login"
),
status_code
=
303
)
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
# Get user-specific providers
user_providers
=
db
.
get_user_providers
(
user_id
)
return
templates
.
TemplateResponse
(
request
=
request
,
name
=
"dashboard/user_providers.html"
,
context
=
{
"request"
:
request
,
"session"
:
request
.
session
,
"user_providers_json"
:
json
.
dumps
(
user_providers
),
"user_id"
:
user_id
}
)
@
app
.
post
(
"/dashboard/user/providers"
)
async
def
dashboard_user_providers_save
(
request
:
Request
,
provider_name
:
str
=
Form
(
...
),
provider_config
:
str
=
Form
(
...
)):
"""Save user-specific provider configuration"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/login"
),
status_code
=
303
)
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
try
:
# Validate JSON
provider_data
=
json
.
loads
(
provider_config
)
# Save to database
db
.
save_user_provider
(
user_id
,
provider_name
,
provider_data
)
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/user/providers"
),
status_code
=
303
)
except
json
.
JSONDecodeError
as
e
:
# Reload current providers on error
user_providers
=
db
.
get_user_providers
(
user_id
)
return
templates
.
TemplateResponse
(
request
=
request
,
name
=
"dashboard/user_providers.html"
,
context
=
{
"request"
:
request
,
"session"
:
request
.
session
,
"user_providers_json"
:
json
.
dumps
(
user_providers
),
"user_id"
:
user_id
,
"error"
:
f
"Invalid JSON: {str(e)}"
}
)
@
app
.
delete
(
"/dashboard/user/providers/{provider_name}"
)
async
def
dashboard_user_providers_delete
(
request
:
Request
,
provider_name
:
str
):
"""Delete user-specific provider configuration"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
JSONResponse
(
status_code
=
401
,
content
=
{
"error"
:
"Not authenticated"
})
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
try
:
db
.
delete_user_provider
(
user_id
,
provider_name
)
return
JSONResponse
({
"message"
:
"Provider deleted successfully"
})
except
Exception
as
e
:
return
JSONResponse
(
status_code
=
500
,
content
=
{
"error"
:
str
(
e
)})
# User authentication file management routes
def
get_user_auth_files_dir
(
user_id
:
int
)
->
Path
:
"""Get the directory for user authentication files"""
auth_files_dir
=
Path
.
home
()
/
'.aisbf'
/
'user_auth_files'
/
str
(
user_id
)
auth_files_dir
.
mkdir
(
parents
=
True
,
exist_ok
=
True
)
return
auth_files_dir
@
app
.
post
(
"/dashboard/user/providers/{provider_name}/upload"
)
async
def
dashboard_user_provider_upload
(
request
:
Request
,
provider_name
:
str
,
file_type
:
str
=
Form
(
...
),
file
:
UploadFile
=
File
(
...
)
):
"""Upload authentication file for a provider"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
JSONResponse
(
status_code
=
401
,
content
=
{
"error"
:
"Not authenticated"
})
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
try
:
# Validate file type
allowed_types
=
[
'credentials'
,
'database'
,
'config'
,
'kiro_credentials'
,
'claude_credentials'
,
'sqlite_db'
,
'creds_file'
]
if
file_type
not
in
allowed_types
:
return
JSONResponse
(
status_code
=
400
,
content
=
{
"error"
:
f
"Invalid file type. Allowed: {', '.join(allowed_types)}"
}
)
# Get user auth files directory
auth_files_dir
=
get_user_auth_files_dir
(
user_id
)
# Generate unique filename
import
uuid
file_ext
=
Path
(
file
.
filename
)
.
suffix
if
file
.
filename
else
'.json'
stored_filename
=
f
"{provider_name}_{file_type}_{uuid.uuid4().hex[:8]}{file_ext}"
file_path
=
auth_files_dir
/
stored_filename
# Save file
content
=
await
file
.
read
()
with
open
(
file_path
,
'wb'
)
as
f
:
f
.
write
(
content
)
# Save metadata to database
file_id
=
db
.
save_user_auth_file
(
user_id
=
user_id
,
provider_id
=
provider_name
,
file_type
=
file_type
,
original_filename
=
file
.
filename
or
stored_filename
,
stored_filename
=
stored_filename
,
file_path
=
str
(
file_path
),
file_size
=
len
(
content
),
mime_type
=
file
.
content_type
)
return
JSONResponse
({
"message"
:
"File uploaded successfully"
,
"file_id"
:
file_id
,
"file_path"
:
str
(
file_path
),
"stored_filename"
:
stored_filename
})
except
Exception
as
e
:
logger
.
error
(
f
"Error uploading file: {e}"
)
return
JSONResponse
(
status_code
=
500
,
content
=
{
"error"
:
str
(
e
)})
@
app
.
get
(
"/dashboard/user/providers/{provider_name}/files"
)
async
def
dashboard_user_provider_files
(
request
:
Request
,
provider_name
:
str
):
"""Get all authentication files for a provider"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
JSONResponse
(
status_code
=
401
,
content
=
{
"error"
:
"Not authenticated"
})
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
try
:
files
=
db
.
get_user_auth_files
(
user_id
,
provider_name
)
return
JSONResponse
({
"files"
:
files
})
except
Exception
as
e
:
return
JSONResponse
(
status_code
=
500
,
content
=
{
"error"
:
str
(
e
)})
@
app
.
get
(
"/dashboard/user/providers/{provider_name}/files/{file_type}/download"
)
async
def
dashboard_user_provider_file_download
(
request
:
Request
,
provider_name
:
str
,
file_type
:
str
):
"""Download an authentication file"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
JSONResponse
(
status_code
=
401
,
content
=
{
"error"
:
"Not authenticated"
})
from
aisbf.database
import
get_database
from
fastapi.responses
import
FileResponse
db
=
DatabaseRegistry
.
get_config_database
()
try
:
file_info
=
db
.
get_user_auth_file
(
user_id
,
provider_name
,
file_type
)
if
not
file_info
:
return
JSONResponse
(
status_code
=
404
,
content
=
{
"error"
:
"File not found"
})
file_path
=
Path
(
file_info
[
'file_path'
])
if
not
file_path
.
exists
():
return
JSONResponse
(
status_code
=
404
,
content
=
{
"error"
:
"File not found on disk"
})
return
FileResponse
(
path
=
str
(
file_path
),
filename
=
file_info
[
'original_filename'
],
media_type
=
file_info
[
'mime_type'
]
or
'application/octet-stream'
)
except
Exception
as
e
:
return
JSONResponse
(
status_code
=
500
,
content
=
{
"error"
:
str
(
e
)})
@
app
.
delete
(
"/dashboard/user/providers/{provider_name}/files/{file_type}"
)
async
def
dashboard_user_provider_file_delete
(
request
:
Request
,
provider_name
:
str
,
file_type
:
str
):
"""Delete an authentication file"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
JSONResponse
(
status_code
=
401
,
content
=
{
"error"
:
"Not authenticated"
})
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
try
:
...
...
@@ -6445,68 +6212,13 @@ async def dashboard_provider_auth_check(request: Request, provider_name: str):
# User-specific rotation management routes
@
app
.
get
(
"/dashboard/user/rotations"
,
response_class
=
HTMLResponse
)
async
def
dashboard_user_rotations
(
request
:
Request
):
"""User rotation management page"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/login"
),
status_code
=
303
)
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
# Get user-specific rotations
user_rotations
=
db
.
get_user_rotations
(
user_id
)
return
templates
.
TemplateResponse
(
request
=
request
,
name
=
"dashboard/user_rotations.html"
,
context
=
{
"request"
:
request
,
"session"
:
request
.
session
,
"user_rotations_json"
:
json
.
dumps
(
user_rotations
),
"user_id"
:
user_id
}
)
"""Redirect to unified rotations endpoint"""
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/rotations"
),
status_code
=
301
)
@
app
.
post
(
"/dashboard/user/rotations"
)
async
def
dashboard_user_rotations_save
(
request
:
Request
,
rotation_name
:
str
=
Form
(
...
),
rotation_config
:
str
=
Form
(
...
)):
"""Save user-specific rotation configuration"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/login"
),
status_code
=
303
)
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
try
:
# Validate JSON
rotation_data
=
json
.
loads
(
rotation_config
)
# Save to database
db
.
save_user_rotation
(
user_id
,
rotation_name
,
rotation_data
)
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/user/rotations"
),
status_code
=
303
)
except
json
.
JSONDecodeError
as
e
:
# Reload current rotations on error
user_rotations
=
db
.
get_user_rotations
(
user_id
)
return
templates
.
TemplateResponse
(
request
=
request
,
name
=
"dashboard/user_rotations.html"
,
context
=
{
"request"
:
request
,
"session"
:
request
.
session
,
"user_rotations_json"
:
json
.
dumps
(
user_rotations
),
"user_id"
:
user_id
,
"error"
:
f
"Invalid JSON: {str(e)}"
}
)
async
def
dashboard_user_rotations_save
(
request
:
Request
,
config
:
str
=
Form
(
...
)):
"""Redirect to unified rotations save endpoint"""
return
await
dashboard_rotations_save
(
request
,
config
)
@
app
.
delete
(
"/dashboard/user/rotations/{rotation_name}"
)
async
def
dashboard_user_rotations_delete
(
request
:
Request
,
rotation_name
:
str
):
...
...
@@ -6531,68 +6243,13 @@ async def dashboard_user_rotations_delete(request: Request, rotation_name: str):
# User-specific autoselect management routes
@
app
.
get
(
"/dashboard/user/autoselects"
,
response_class
=
HTMLResponse
)
async
def
dashboard_user_autoselects
(
request
:
Request
):
"""User autoselect management page"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/login"
),
status_code
=
303
)
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
# Get user-specific autoselects
user_autoselects
=
db
.
get_user_autoselects
(
user_id
)
return
templates
.
TemplateResponse
(
request
=
request
,
name
=
"dashboard/user_autoselects.html"
,
context
=
{
"request"
:
request
,
"session"
:
request
.
session
,
"user_autoselects_json"
:
json
.
dumps
(
user_autoselects
),
"user_id"
:
user_id
}
)
"""Redirect to unified autoselect endpoint"""
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/autoselect"
),
status_code
=
301
)
@
app
.
post
(
"/dashboard/user/autoselects"
)
async
def
dashboard_user_autoselects_save
(
request
:
Request
,
autoselect_name
:
str
=
Form
(
...
),
autoselect_config
:
str
=
Form
(
...
)):
"""Save user-specific autoselect configuration"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
user_id
=
request
.
session
.
get
(
'user_id'
)
if
not
user_id
:
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/login"
),
status_code
=
303
)
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
try
:
# Validate JSON
autoselect_data
=
json
.
loads
(
autoselect_config
)
# Save to database
db
.
save_user_autoselect
(
user_id
,
autoselect_name
,
autoselect_data
)
return
RedirectResponse
(
url
=
url_for
(
request
,
"/dashboard/user/autoselects"
),
status_code
=
303
)
except
json
.
JSONDecodeError
as
e
:
# Reload current autoselects on error
user_autoselects
=
db
.
get_user_autoselects
(
user_id
)
return
templates
.
TemplateResponse
(
request
=
request
,
name
=
"dashboard/user_autoselects.html"
,
context
=
{
"request"
:
request
,
"session"
:
request
.
session
,
"user_autoselects_json"
:
json
.
dumps
(
user_autoselects
),
"user_id"
:
user_id
,
"error"
:
f
"Invalid JSON: {str(e)}"
}
)
async
def
dashboard_user_autoselects_save
(
request
:
Request
,
config
:
str
=
Form
(
...
)):
"""Redirect to unified autoselect save endpoint"""
return
await
dashboard_autoselect_save
(
request
,
config
)
@
app
.
delete
(
"/dashboard/user/autoselects/{autoselect_name}"
)
async
def
dashboard_user_autoselects_delete
(
request
:
Request
,
autoselect_name
:
str
):
...
...
@@ -6731,66 +6388,6 @@ async def dashboard_user_tokens_delete(request: Request, token_id: int):
try
:
db
.
delete_user_api_token
(
user_id
,
token_id
)
return
JSONResponse
({
"message"
:
"Token deleted successfully"
})
except
Exception
as
e
:
return
JSONResponse
(
status_code
=
500
,
content
=
{
"error"
:
str
(
e
)})
@
app
.
get
(
"/dashboard/tor/status"
)
async
def
dashboard_tor_status
(
request
:
Request
):
"""Get TOR hidden service status"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
global
tor_service
if
tor_service
:
status
=
tor_service
.
get_status
()
else
:
status
=
{
'enabled'
:
False
,
'connected'
:
False
,
'onion_address'
:
None
,
'service_id'
:
None
,
'control_host'
:
None
,
'control_port'
:
None
,
'hidden_service_port'
:
None
}
return
JSONResponse
(
status
)
@
app
.
get
(
"/dashboard/response-cache"
)
async
def
dashboard_response_cache
(
request
:
Request
):
"""Response cache management page"""
auth_check
=
require_dashboard_auth
(
request
)
if
auth_check
:
return
auth_check
from
aisbf.cache
import
get_response_cache
try
:
cache
=
get_response_cache
()
stats
=
cache
.
get_stats
()
except
Exception
as
e
:
logger
.
error
(
f
"Error getting response cache stats: {e}"
)
stats
=
{
'enabled'
:
False
,
'hits'
:
0
,
'misses'
:
0
,
'hit_rate'
:
0.0
,
'size'
:
0
,
'evictions'
:
0
,
'backend'
:
'unknown'
,
'error'
:
str
(
e
)
}
return
templates
.
TemplateResponse
(
request
=
request
,
name
=
"dashboard/response_cache.html"
,
context
=
{
"request"
:
request
,
"session"
:
request
.
session
,
"stats"
:
stats
}
)
...
...
pyproject.toml
View file @
d39326be
...
...
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name
=
"aisbf"
version
=
"0.99.3
5
"
version
=
"0.99.3
6
"
description
=
"AISBF - AI Service Broker Framework || AI Should Be Free - A modular proxy server for managing multiple AI provider integrations"
readme
=
"README.md"
license
=
"GPL-3.0-or-later"
...
...
setup.py
View file @
d39326be
...
...
@@ -49,7 +49,7 @@ class InstallCommand(_install):
setup
(
name
=
"aisbf"
,
version
=
"0.99.3
5
"
,
version
=
"0.99.3
6
"
,
author
=
"AISBF Contributors"
,
author_email
=
"stefy@nexlab.net"
,
description
=
"AISBF - AI Service Broker Framework || AI Should Be Free - A modular proxy server for managing multiple AI provider integrations"
,
...
...
templates/dashboard/providers.html
View file @
d39326be
...
...
@@ -1748,6 +1748,9 @@ async function confirmAddProvider() {
};
}
// Add to expanded providers so it automatically expands
expandedProviders
.
add
(
key
);
cancelAddProvider
();
renderProvidersList
();
}
...
...
templates/dashboard/user_providers.html
View file @
d39326be
...
...
@@ -1699,6 +1699,9 @@ async function confirmAddProvider() {
};
}
// Add to expanded providers so it automatically expands
expandedProviders
.
add
(
key
);
cancelAddProvider
();
renderProvidersList
();
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment