mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-20 23:32:19 +00:00
feat(registries): add private registry credential management (Team Pro) (#240)
Add centralized credential storage for private Docker registries with support for Docker Hub, GHCR, AWS ECR, and self-hosted registries. - New `registries` table with AES-256-GCM encrypted secrets - RegistryService with CRUD, test connectivity, Docker config generation - 5 API endpoints gated by requireTeamPro + requireAdmin - ComposeService injects credentials via temp DOCKER_CONFIG on deploy/pull - ImageUpdateService passes stored credentials for private registry checks - AWS ECR just-in-time token refresh via @aws-sdk/client-ecr - RegistriesSection UI in Settings Hub with type-aware form - Documentation with screenshots
This commit is contained in:
@@ -29,6 +29,7 @@ import { TierBadge } from './TierBadge';
|
||||
import { ProGate } from './ProGate';
|
||||
import { SSOSection } from './SSOSection';
|
||||
import { ApiTokensSection } from './ApiTokensSection';
|
||||
import { RegistriesSection } from './RegistriesSection';
|
||||
|
||||
interface Agent {
|
||||
type: 'discord' | 'slack' | 'webhook';
|
||||
@@ -50,7 +51,7 @@ interface PatchableSettings {
|
||||
log_retention_days?: string;
|
||||
}
|
||||
|
||||
type SectionId = 'account' | 'license' | 'users' | 'sso' | 'api-tokens' | 'system' | 'notifications' | 'webhooks' | 'developer' | 'nodes' | 'appstore' | 'support' | 'about';
|
||||
type SectionId = 'account' | 'license' | 'users' | 'sso' | 'api-tokens' | 'registries' | 'system' | 'notifications' | 'webhooks' | 'developer' | 'nodes' | 'appstore' | 'support' | 'about';
|
||||
|
||||
interface WebhookItem {
|
||||
id: number;
|
||||
@@ -658,7 +659,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 === 'api-tokens' || activeSection === 'notifications' || activeSection === 'webhooks' || activeSection === 'nodes' || activeSection === 'appstore')) {
|
||||
if (isRemote && (activeSection === 'account' || activeSection === 'license' || activeSection === 'users' || activeSection === 'sso' || activeSection === 'api-tokens' || activeSection === 'registries' || activeSection === 'notifications' || activeSection === 'webhooks' || activeSection === 'nodes' || activeSection === 'appstore')) {
|
||||
setActiveSection('system');
|
||||
}
|
||||
}, [isRemote]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
@@ -1005,6 +1006,9 @@ export function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
||||
{!isRemote && isAdmin && isPro && license?.variant === 'team' && (
|
||||
<NavButton section="api-tokens" icon={<Zap className="w-4 h-4 mr-2" />} label="API Tokens" />
|
||||
)}
|
||||
{!isRemote && isAdmin && isPro && license?.variant === 'team' && (
|
||||
<NavButton section="registries" icon={<Database className="w-4 h-4 mr-2" />} label="Registries" />
|
||||
)}
|
||||
<NavButton
|
||||
section="system"
|
||||
icon={<Activity className="w-4 h-4 mr-2" />}
|
||||
@@ -1468,6 +1472,10 @@ export function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
||||
<ApiTokensSection />
|
||||
)}
|
||||
|
||||
{activeSection === 'registries' && (
|
||||
<RegistriesSection />
|
||||
)}
|
||||
|
||||
{activeSection === 'developer' && (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-start justify-between pr-8">
|
||||
|
||||
Reference in New Issue
Block a user