2 Commits

7 changed files with 23 additions and 44 deletions

View File

@@ -20,7 +20,6 @@ type APIKey struct {
UserID string UserID string
PermissionMode PermissionMode PermissionMode PermissionMode
ExpiresAt *int64 ExpiresAt *int64
Enabled bool
CreatedAt int64 CreatedAt int64
UpdatedAt int64 UpdatedAt int64
LastUsedAt *int64 LastUsedAt *int64
@@ -29,7 +28,6 @@ type APIKey struct {
type KeyPermission struct { type KeyPermission struct {
KeyID int KeyID int
InstanceID int InstanceID int
CanInfer bool
} }
// GenerateKey generates a cryptographically secure API key with the given prefix // GenerateKey generates a cryptographically secure API key with the given prefix

View File

@@ -18,8 +18,8 @@ func (db *sqliteDB) CreateKey(ctx context.Context, key *auth.APIKey, permissions
// Insert the API key // Insert the API key
query := ` query := `
INSERT INTO api_keys (key_hash, name, user_id, permission_mode, expires_at, enabled, created_at, updated_at) INSERT INTO api_keys (key_hash, name, user_id, permission_mode, expires_at, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?)
` `
var expiresAt sql.NullInt64 var expiresAt sql.NullInt64
@@ -29,7 +29,7 @@ func (db *sqliteDB) CreateKey(ctx context.Context, key *auth.APIKey, permissions
result, err := tx.ExecContext(ctx, query, result, err := tx.ExecContext(ctx, query,
key.KeyHash, key.Name, key.UserID, key.PermissionMode, key.KeyHash, key.Name, key.UserID, key.PermissionMode,
expiresAt, key.Enabled, key.CreatedAt, key.UpdatedAt, expiresAt, key.CreatedAt, key.UpdatedAt,
) )
if err != nil { if err != nil {
return fmt.Errorf("failed to insert API key: %w", err) return fmt.Errorf("failed to insert API key: %w", err)
@@ -45,10 +45,10 @@ func (db *sqliteDB) CreateKey(ctx context.Context, key *auth.APIKey, permissions
if key.PermissionMode == auth.PermissionModePerInstance { if key.PermissionMode == auth.PermissionModePerInstance {
for _, perm := range permissions { for _, perm := range permissions {
query := ` query := `
INSERT INTO key_permissions (key_id, instance_id, can_infer) INSERT INTO key_permissions (key_id, instance_id)
VALUES (?, ?, ?) VALUES (?, ?)
` `
_, err := tx.ExecContext(ctx, query, key.ID, perm.InstanceID, perm.CanInfer) _, err := tx.ExecContext(ctx, query, key.ID, perm.InstanceID)
if err != nil { if err != nil {
return fmt.Errorf("failed to insert permission for instance %d: %w", perm.InstanceID, err) return fmt.Errorf("failed to insert permission for instance %d: %w", perm.InstanceID, err)
} }
@@ -61,7 +61,7 @@ func (db *sqliteDB) CreateKey(ctx context.Context, key *auth.APIKey, permissions
// GetKeyByID retrieves an API key by ID // GetKeyByID retrieves an API key by ID
func (db *sqliteDB) GetKeyByID(ctx context.Context, id int) (*auth.APIKey, error) { func (db *sqliteDB) GetKeyByID(ctx context.Context, id int) (*auth.APIKey, error) {
query := ` query := `
SELECT id, key_hash, name, user_id, permission_mode, expires_at, enabled, created_at, updated_at, last_used_at SELECT id, key_hash, name, user_id, permission_mode, expires_at, created_at, updated_at, last_used_at
FROM api_keys FROM api_keys
WHERE id = ? WHERE id = ?
` `
@@ -72,7 +72,7 @@ func (db *sqliteDB) GetKeyByID(ctx context.Context, id int) (*auth.APIKey, error
err := db.QueryRowContext(ctx, query, id).Scan( err := db.QueryRowContext(ctx, query, id).Scan(
&key.ID, &key.KeyHash, &key.Name, &key.UserID, &key.PermissionMode, &key.ID, &key.KeyHash, &key.Name, &key.UserID, &key.PermissionMode,
&expiresAt, &key.Enabled, &key.CreatedAt, &key.UpdatedAt, &lastUsedAt, &expiresAt, &key.CreatedAt, &key.UpdatedAt, &lastUsedAt,
) )
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
@@ -94,7 +94,7 @@ func (db *sqliteDB) GetKeyByID(ctx context.Context, id int) (*auth.APIKey, error
// GetUserKeys retrieves all API keys for a user // GetUserKeys retrieves all API keys for a user
func (db *sqliteDB) GetUserKeys(ctx context.Context, userID string) ([]*auth.APIKey, error) { func (db *sqliteDB) GetUserKeys(ctx context.Context, userID string) ([]*auth.APIKey, error) {
query := ` query := `
SELECT id, key_hash, name, user_id, permission_mode, expires_at, enabled, created_at, updated_at, last_used_at SELECT id, key_hash, name, user_id, permission_mode, expires_at, created_at, updated_at, last_used_at
FROM api_keys FROM api_keys
WHERE user_id = ? WHERE user_id = ?
ORDER BY created_at DESC ORDER BY created_at DESC
@@ -114,7 +114,7 @@ func (db *sqliteDB) GetUserKeys(ctx context.Context, userID string) ([]*auth.API
err := rows.Scan( err := rows.Scan(
&key.ID, &key.KeyHash, &key.Name, &key.UserID, &key.PermissionMode, &key.ID, &key.KeyHash, &key.Name, &key.UserID, &key.PermissionMode,
&expiresAt, &key.Enabled, &key.CreatedAt, &key.UpdatedAt, &lastUsedAt, &expiresAt, &key.CreatedAt, &key.UpdatedAt, &lastUsedAt,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to scan API key: %w", err) return nil, fmt.Errorf("failed to scan API key: %w", err)
@@ -133,12 +133,12 @@ func (db *sqliteDB) GetUserKeys(ctx context.Context, userID string) ([]*auth.API
return keys, nil return keys, nil
} }
// GetActiveKeys retrieves all enabled, non-expired API keys // GetActiveKeys retrieves all non-expired API keys
func (db *sqliteDB) GetActiveKeys(ctx context.Context) ([]*auth.APIKey, error) { func (db *sqliteDB) GetActiveKeys(ctx context.Context) ([]*auth.APIKey, error) {
query := ` query := `
SELECT id, key_hash, name, user_id, permission_mode, expires_at, enabled, created_at, updated_at, last_used_at SELECT id, key_hash, name, user_id, permission_mode, expires_at, created_at, updated_at, last_used_at
FROM api_keys FROM api_keys
WHERE enabled = 1 AND (expires_at IS NULL OR expires_at > ?) WHERE expires_at IS NULL OR expires_at > ?
ORDER BY created_at DESC ORDER BY created_at DESC
` `
@@ -157,7 +157,7 @@ func (db *sqliteDB) GetActiveKeys(ctx context.Context) ([]*auth.APIKey, error) {
err := rows.Scan( err := rows.Scan(
&key.ID, &key.KeyHash, &key.Name, &key.UserID, &key.PermissionMode, &key.ID, &key.KeyHash, &key.Name, &key.UserID, &key.PermissionMode,
&expiresAt, &key.Enabled, &key.CreatedAt, &key.UpdatedAt, &lastUsedAt, &expiresAt, &key.CreatedAt, &key.UpdatedAt, &lastUsedAt,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to scan API key: %w", err) return nil, fmt.Errorf("failed to scan API key: %w", err)

View File

@@ -36,7 +36,6 @@ CREATE TABLE IF NOT EXISTS api_keys (
user_id TEXT NOT NULL, user_id TEXT NOT NULL,
permission_mode TEXT NOT NULL CHECK(permission_mode IN ('allow_all', 'per_instance')) DEFAULT 'per_instance', permission_mode TEXT NOT NULL CHECK(permission_mode IN ('allow_all', 'per_instance')) DEFAULT 'per_instance',
expires_at INTEGER NULL, expires_at INTEGER NULL,
enabled INTEGER NOT NULL DEFAULT 1,
created_at INTEGER NOT NULL, created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL, updated_at INTEGER NOT NULL,
last_used_at INTEGER NULL last_used_at INTEGER NULL
@@ -48,7 +47,6 @@ CREATE TABLE IF NOT EXISTS api_keys (
CREATE TABLE IF NOT EXISTS key_permissions ( CREATE TABLE IF NOT EXISTS key_permissions (
key_id INTEGER NOT NULL, key_id INTEGER NOT NULL,
instance_id INTEGER NOT NULL, instance_id INTEGER NOT NULL,
can_infer INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (key_id, instance_id), PRIMARY KEY (key_id, instance_id),
FOREIGN KEY (key_id) REFERENCES api_keys (id) ON DELETE CASCADE, FOREIGN KEY (key_id) REFERENCES api_keys (id) ON DELETE CASCADE,
FOREIGN KEY (instance_id) REFERENCES instances (id) ON DELETE CASCADE FOREIGN KEY (instance_id) REFERENCES instances (id) ON DELETE CASCADE

View File

@@ -10,7 +10,7 @@ import (
// GetPermissions retrieves all permissions for a key // GetPermissions retrieves all permissions for a key
func (db *sqliteDB) GetPermissions(ctx context.Context, keyID int) ([]auth.KeyPermission, error) { func (db *sqliteDB) GetPermissions(ctx context.Context, keyID int) ([]auth.KeyPermission, error) {
query := ` query := `
SELECT key_id, instance_id, can_infer SELECT key_id, instance_id
FROM key_permissions FROM key_permissions
WHERE key_id = ? WHERE key_id = ?
ORDER BY instance_id ORDER BY instance_id
@@ -25,7 +25,7 @@ func (db *sqliteDB) GetPermissions(ctx context.Context, keyID int) ([]auth.KeyPe
var permissions []auth.KeyPermission var permissions []auth.KeyPermission
for rows.Next() { for rows.Next() {
var perm auth.KeyPermission var perm auth.KeyPermission
err := rows.Scan(&perm.KeyID, &perm.InstanceID, &perm.CanInfer) err := rows.Scan(&perm.KeyID, &perm.InstanceID)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to scan key permission: %w", err) return nil, fmt.Errorf("failed to scan key permission: %w", err)
} }
@@ -38,13 +38,13 @@ func (db *sqliteDB) GetPermissions(ctx context.Context, keyID int) ([]auth.KeyPe
// HasPermission checks if key has inference permission for instance // HasPermission checks if key has inference permission for instance
func (db *sqliteDB) HasPermission(ctx context.Context, keyID, instanceID int) (bool, error) { func (db *sqliteDB) HasPermission(ctx context.Context, keyID, instanceID int) (bool, error) {
query := ` query := `
SELECT can_infer SELECT 1
FROM key_permissions FROM key_permissions
WHERE key_id = ? AND instance_id = ? WHERE key_id = ? AND instance_id = ?
` `
var canInfer bool var exists int
err := db.QueryRowContext(ctx, query, keyID, instanceID).Scan(&canInfer) err := db.QueryRowContext(ctx, query, keyID, instanceID).Scan(&exists)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
// No permission record found, deny access // No permission record found, deny access
@@ -53,5 +53,5 @@ func (db *sqliteDB) HasPermission(ctx context.Context, keyID, instanceID int) (b
return false, fmt.Errorf("failed to check key permission: %w", err) return false, fmt.Errorf("failed to check key permission: %w", err)
} }
return canInfer, nil return true, nil
} }

View File

@@ -13,8 +13,7 @@ import (
// InstancePermission defines the permissions for an API key on a specific instance. // InstancePermission defines the permissions for an API key on a specific instance.
type InstancePermission struct { type InstancePermission struct {
InstanceID int `json:"instance_id"` InstanceID int `json:"instance_id"`
CanInfer bool `json:"can_infer"`
} }
// CreateKeyRequest represents the request body for creating a new API key. // CreateKeyRequest represents the request body for creating a new API key.
@@ -32,7 +31,6 @@ type CreateKeyResponse struct {
UserID string `json:"user_id"` UserID string `json:"user_id"`
PermissionMode auth.PermissionMode `json:"permission_mode"` PermissionMode auth.PermissionMode `json:"permission_mode"`
ExpiresAt *int64 `json:"expires_at"` ExpiresAt *int64 `json:"expires_at"`
Enabled bool `json:"enabled"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
LastUsedAt *int64 `json:"last_used_at"` LastUsedAt *int64 `json:"last_used_at"`
@@ -46,7 +44,6 @@ type KeyResponse struct {
UserID string `json:"user_id"` UserID string `json:"user_id"`
PermissionMode auth.PermissionMode `json:"permission_mode"` PermissionMode auth.PermissionMode `json:"permission_mode"`
ExpiresAt *int64 `json:"expires_at"` ExpiresAt *int64 `json:"expires_at"`
Enabled bool `json:"enabled"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
LastUsedAt *int64 `json:"last_used_at"` LastUsedAt *int64 `json:"last_used_at"`
@@ -56,7 +53,6 @@ type KeyResponse struct {
type KeyPermissionResponse struct { type KeyPermissionResponse struct {
InstanceID int `json:"instance_id"` InstanceID int `json:"instance_id"`
InstanceName string `json:"instance_name"` InstanceName string `json:"instance_name"`
CanInfer bool `json:"can_infer"`
} }
// CreateKey godoc // CreateKey godoc
@@ -142,7 +138,6 @@ func (h *Handler) CreateKey() http.HandlerFunc {
UserID: "system", UserID: "system",
PermissionMode: req.PermissionMode, PermissionMode: req.PermissionMode,
ExpiresAt: req.ExpiresAt, ExpiresAt: req.ExpiresAt,
Enabled: true,
CreatedAt: now, CreatedAt: now,
UpdatedAt: now, UpdatedAt: now,
} }
@@ -153,7 +148,6 @@ func (h *Handler) CreateKey() http.HandlerFunc {
keyPermissions = append(keyPermissions, auth.KeyPermission{ keyPermissions = append(keyPermissions, auth.KeyPermission{
KeyID: 0, // Will be set by database after key creation KeyID: 0, // Will be set by database after key creation
InstanceID: perm.InstanceID, InstanceID: perm.InstanceID,
CanInfer: perm.CanInfer,
}) })
} }
@@ -171,7 +165,6 @@ func (h *Handler) CreateKey() http.HandlerFunc {
UserID: apiKey.UserID, UserID: apiKey.UserID,
PermissionMode: apiKey.PermissionMode, PermissionMode: apiKey.PermissionMode,
ExpiresAt: apiKey.ExpiresAt, ExpiresAt: apiKey.ExpiresAt,
Enabled: apiKey.Enabled,
CreatedAt: apiKey.CreatedAt, CreatedAt: apiKey.CreatedAt,
UpdatedAt: apiKey.UpdatedAt, UpdatedAt: apiKey.UpdatedAt,
LastUsedAt: apiKey.LastUsedAt, LastUsedAt: apiKey.LastUsedAt,
@@ -210,7 +203,6 @@ func (h *Handler) ListKeys() http.HandlerFunc {
UserID: key.UserID, UserID: key.UserID,
PermissionMode: key.PermissionMode, PermissionMode: key.PermissionMode,
ExpiresAt: key.ExpiresAt, ExpiresAt: key.ExpiresAt,
Enabled: key.Enabled,
CreatedAt: key.CreatedAt, CreatedAt: key.CreatedAt,
UpdatedAt: key.UpdatedAt, UpdatedAt: key.UpdatedAt,
LastUsedAt: key.LastUsedAt, LastUsedAt: key.LastUsedAt,
@@ -260,7 +252,6 @@ func (h *Handler) GetKey() http.HandlerFunc {
UserID: key.UserID, UserID: key.UserID,
PermissionMode: key.PermissionMode, PermissionMode: key.PermissionMode,
ExpiresAt: key.ExpiresAt, ExpiresAt: key.ExpiresAt,
Enabled: key.Enabled,
CreatedAt: key.CreatedAt, CreatedAt: key.CreatedAt,
UpdatedAt: key.UpdatedAt, UpdatedAt: key.UpdatedAt,
LastUsedAt: key.LastUsedAt, LastUsedAt: key.LastUsedAt,
@@ -359,7 +350,6 @@ func (h *Handler) GetKeyPermissions() http.HandlerFunc {
response = append(response, KeyPermissionResponse{ response = append(response, KeyPermissionResponse{
InstanceID: perm.InstanceID, InstanceID: perm.InstanceID,
InstanceName: instanceNameMap[perm.InstanceID], InstanceName: instanceNameMap[perm.InstanceID],
CanInfer: perm.CanInfer,
}) })
} }

View File

@@ -249,11 +249,7 @@ function ApiKeysSection() {
<tr key={perm.instance_id} className="border-b"> <tr key={perm.instance_id} className="border-b">
<td className="py-2">{perm.instance_name}</td> <td className="py-2">{perm.instance_name}</td>
<td className="py-2"> <td className="py-2">
{perm.can_infer ? ( <Check className="h-4 w-4 text-green-600" />
<Check className="h-4 w-4 text-green-600" />
) : (
<X className="h-4 w-4 text-red-600" />
)}
</td> </td>
</tr> </tr>
))} ))}

View File

@@ -9,7 +9,6 @@ export interface ApiKey {
user_id: string user_id: string
permission_mode: PermissionMode permission_mode: PermissionMode
expires_at: number | null expires_at: number | null
enabled: boolean
created_at: number created_at: number
updated_at: number updated_at: number
last_used_at: number | null last_used_at: number | null
@@ -24,7 +23,6 @@ export interface CreateKeyRequest {
export interface InstancePermission { export interface InstancePermission {
InstanceID: number InstanceID: number
CanInfer: boolean
} }
export interface CreateKeyResponse extends ApiKey { export interface CreateKeyResponse extends ApiKey {
@@ -34,5 +32,4 @@ export interface CreateKeyResponse extends ApiKey {
export interface KeyPermissionResponse { export interface KeyPermissionResponse {
instance_id: number instance_id: number
instance_name: string instance_name: string
can_infer: boolean
} }