mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-30 12:09:15 +00:00
feat(api-tokens): add scoped API tokens for CI/CD automation (Team Pro) (#220)
Add long-lived API tokens with three permission scopes (read-only, deploy-only, full-admin) for CI/CD pipelines, scripts, and automation. - Database: api_tokens table with SHA-256 hashed storage - Auth: extend middleware to authenticate Bearer API tokens - Scope enforcement: middleware restricts actions per token scope - API: CRUD endpoints gated behind Team Pro + admin - UI: ApiTokensSection in Settings Hub with create/revoke/copy flows - Docs: new api-tokens.mdx with usage examples and screenshots
This commit is contained in:
@@ -28,6 +28,7 @@ import { useLicense } from '@/context/LicenseContext';
|
||||
import { TierBadge } from './TierBadge';
|
||||
import { ProGate } from './ProGate';
|
||||
import { SSOSection } from './SSOSection';
|
||||
import { ApiTokensSection } from './ApiTokensSection';
|
||||
|
||||
interface Agent {
|
||||
type: 'discord' | 'slack' | 'webhook';
|
||||
@@ -49,7 +50,7 @@ interface PatchableSettings {
|
||||
log_retention_days?: string;
|
||||
}
|
||||
|
||||
type SectionId = 'account' | 'license' | 'users' | 'sso' | 'system' | 'notifications' | 'webhooks' | 'developer' | 'nodes' | 'appstore' | 'support' | 'about';
|
||||
type SectionId = 'account' | 'license' | 'users' | 'sso' | 'api-tokens' | 'system' | 'notifications' | 'webhooks' | 'developer' | 'nodes' | 'appstore' | 'support' | 'about';
|
||||
|
||||
interface WebhookItem {
|
||||
id: number;
|
||||
@@ -657,7 +658,7 @@ export function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
||||
|
||||
// When switching to a remote node, reset to a node-scoped section if on a global-only one
|
||||
useEffect(() => {
|
||||
if (isRemote && (activeSection === 'account' || activeSection === 'license' || activeSection === 'users' || activeSection === 'sso' || activeSection === 'notifications' || activeSection === 'webhooks' || activeSection === 'nodes' || activeSection === 'appstore')) {
|
||||
if (isRemote && (activeSection === 'account' || activeSection === 'license' || activeSection === 'users' || activeSection === 'sso' || activeSection === 'api-tokens' || activeSection === 'notifications' || activeSection === 'webhooks' || activeSection === 'nodes' || activeSection === 'appstore')) {
|
||||
setActiveSection('system');
|
||||
}
|
||||
}, [isRemote]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
@@ -1001,6 +1002,9 @@ export function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
||||
{!isRemote && isAdmin && isPro && license?.variant === 'team' && (
|
||||
<NavButton section="sso" icon={<Shield className="w-4 h-4 mr-2" />} label="SSO" />
|
||||
)}
|
||||
{!isRemote && isAdmin && isPro && license?.variant === 'team' && (
|
||||
<NavButton section="api-tokens" icon={<Zap className="w-4 h-4 mr-2" />} label="API Tokens" />
|
||||
)}
|
||||
<NavButton
|
||||
section="system"
|
||||
icon={<Activity className="w-4 h-4 mr-2" />}
|
||||
@@ -1460,6 +1464,10 @@ export function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
||||
<SSOSection />
|
||||
)}
|
||||
|
||||
{activeSection === 'api-tokens' && (
|
||||
<ApiTokensSection />
|
||||
)}
|
||||
|
||||
{activeSection === 'developer' && (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-start justify-between pr-8">
|
||||
|
||||
Reference in New Issue
Block a user