Skip to content

Commit 5cd79cf

Browse files
committed
feat: implement global settings initialization and define GitHub OAuth and SMTP configuration modules
1 parent 6f3789b commit 5cd79cf

File tree

6 files changed

+693
-0
lines changed

6 files changed

+693
-0
lines changed

services/backend/GLOBAL_SETTINGS.md

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,22 @@ This document describes the global key-value store system for managing applicati
77
The global settings system provides secure storage for application-wide configuration values such as:
88

99
- **SMTP Server Credentials**: Host, port, username, password for email functionality
10+
- **OAuth Credentials**: GitHub OAuth client ID and secret for authentication
1011
- **API Keys**: External service credentials (OpenAI, AWS, etc.)
1112
- **System Configuration**: Application-wide settings and feature flags
1213
- **Integration Credentials**: Third-party service authentication tokens
1314
- **Environment Variables**: Dynamic configuration that can be changed without code deployment
1415

16+
### Auto-Initialization System
17+
18+
The system includes an **auto-initialization feature** that automatically creates missing global settings when the server starts. Settings are defined in modular files within the `src/global-settings/` directory, and the system will:
19+
20+
- Scan for setting definition files on startup
21+
- Check which settings exist in the database
22+
- Create missing settings with default values (non-destructive)
23+
- Preserve existing settings and their values
24+
- Log initialization results for transparency
25+
1526
## Key Features
1627

1728
- **Hierarchical Keys**: Dot notation organization (e.g., `smtp.host`, `api.openai.key`)
@@ -487,6 +498,231 @@ curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer <toke
487498
-d '{"pattern":"smtp"}' http://localhost:3000/api/settings/search
488499
```
489500

501+
## Auto-Initialization System
502+
503+
### Overview
504+
505+
The auto-initialization system automatically creates missing global settings when the server starts. This ensures that all required settings are available without manual configuration, while preserving existing values.
506+
507+
### File-Based Setting Definitions
508+
509+
Settings are defined in TypeScript files within the `src/global-settings/` directory:
510+
511+
```text
512+
src/global-settings/
513+
├── types.ts # Type definitions
514+
├── index.ts # Auto-discovery service
515+
├── smtp.ts # SMTP configuration
516+
├── github-oauth.ts # GitHub OAuth settings
517+
└── [custom].ts # Your custom settings
518+
```
519+
520+
### Setting Definition Format
521+
522+
Each setting file exports a `GlobalSettingsModule`:
523+
524+
```typescript
525+
// src/global-settings/smtp.ts
526+
import type { GlobalSettingsModule } from './types';
527+
528+
export const smtpSettings: GlobalSettingsModule = {
529+
category: 'smtp',
530+
settings: [
531+
{
532+
key: 'smtp.host',
533+
defaultValue: '',
534+
description: 'SMTP server hostname (e.g., smtp.gmail.com)',
535+
encrypted: false,
536+
required: true
537+
},
538+
{
539+
key: 'smtp.password',
540+
defaultValue: '',
541+
description: 'SMTP authentication password',
542+
encrypted: true,
543+
required: true
544+
}
545+
// ... more settings
546+
]
547+
};
548+
```
549+
550+
### Startup Behavior
551+
552+
When the server starts:
553+
554+
1. **Discovery**: Scans `src/global-settings/` for `.ts` files
555+
2. **Loading**: Dynamically imports each settings module
556+
3. **Validation**: Ensures each module has the correct structure
557+
4. **Database Check**: Checks which settings exist in the database
558+
5. **Creation**: Creates missing settings with default values
559+
6. **Preservation**: Skips existing settings (non-destructive)
560+
7. **Logging**: Reports initialization results
561+
562+
### Example Startup Output
563+
564+
```text
565+
🔄 Loading global settings definitions...
566+
📁 Found 2 setting files: smtp, github-oauth
567+
✅ Loaded settings module: smtp (7 settings)
568+
✅ Loaded settings module: github-oauth (5 settings)
569+
🎉 Loaded 2 settings modules with 12 total settings
570+
🔄 Initializing 12 global settings...
571+
✅ Created setting: smtp.host
572+
✅ Created setting: smtp.port
573+
✅ Created setting: smtp.username
574+
✅ Created setting: smtp.password
575+
⏭️ Skipped existing setting: smtp.secure
576+
✅ Created setting: github.oauth.client_id
577+
✅ Created setting: github.oauth.client_secret
578+
🎉 Global settings initialization complete: 6 created, 1 skipped
579+
⚠️ Missing required settings: smtp.host, smtp.username, smtp.password
580+
```
581+
582+
### Built-in Setting Categories
583+
584+
#### SMTP Settings
585+
586+
| Key | Default | Required | Encrypted | Description |
587+
|-----|---------|----------|-----------|-------------|
588+
| `smtp.host` | `''` ||| SMTP server hostname |
589+
| `smtp.port` | `'587'` ||| SMTP server port |
590+
| `smtp.username` | `''` ||| SMTP authentication username |
591+
| `smtp.password` | `''` ||| SMTP authentication password |
592+
| `smtp.secure` | `'true'` ||| Use SSL/TLS connection |
593+
| `smtp.from_name` | `'DeployStack'` ||| Default sender name |
594+
| `smtp.from_email` | `''` ||| Default sender email |
595+
596+
#### GitHub OAuth Settings
597+
598+
| Key | Default | Required | Encrypted | Description |
599+
|-----|---------|----------|-----------|-------------|
600+
| `github.oauth.client_id` | `''` ||| GitHub OAuth client ID |
601+
| `github.oauth.client_secret` | `''` ||| GitHub OAuth client secret |
602+
| `github.oauth.enabled` | `'false'` ||| Enable GitHub OAuth |
603+
| `github.oauth.callback_url` | `'http://localhost:3000/api/auth/github/callback'` ||| OAuth callback URL |
604+
| `github.oauth.scope` | `'user:email'` ||| OAuth requested scopes |
605+
606+
### Helper Methods
607+
608+
The system provides helper methods for retrieving complete configurations:
609+
610+
```typescript
611+
import { GlobalSettingsInitService } from '../global-settings';
612+
613+
// Get complete SMTP configuration
614+
const smtpConfig = await GlobalSettingsInitService.getSmtpConfiguration();
615+
if (smtpConfig) {
616+
// Use smtpConfig.host, smtpConfig.port, etc.
617+
}
618+
619+
// Get complete GitHub OAuth configuration
620+
const githubConfig = await GlobalSettingsInitService.getGitHubOAuthConfiguration();
621+
if (githubConfig && githubConfig.enabled) {
622+
// Use githubConfig.clientId, githubConfig.clientSecret, etc.
623+
}
624+
625+
// Check if services are configured
626+
const isSmtpReady = await GlobalSettingsInitService.isSmtpConfigured();
627+
const isGitHubReady = await GlobalSettingsInitService.isGitHubOAuthConfigured();
628+
```
629+
630+
### Adding New Setting Categories
631+
632+
To add a new setting category:
633+
634+
1. **Create Setting File**: Add a new `.ts` file in `src/global-settings/`
635+
636+
```typescript
637+
// src/global-settings/my-service.ts
638+
import type { GlobalSettingsModule } from './types';
639+
640+
export const myServiceSettings: GlobalSettingsModule = {
641+
category: 'my-service',
642+
settings: [
643+
{
644+
key: 'my-service.api_key',
645+
defaultValue: '',
646+
description: 'API key for My Service',
647+
encrypted: true,
648+
required: true
649+
},
650+
{
651+
key: 'my-service.enabled',
652+
defaultValue: 'false',
653+
description: 'Enable My Service integration',
654+
encrypted: false,
655+
required: false
656+
}
657+
]
658+
};
659+
```
660+
661+
2. **Restart Server**: The new settings will be automatically discovered and initialized
662+
663+
3. **Add Helper Method** (optional): Add a helper method to `GlobalSettingsInitService`
664+
665+
```typescript
666+
// In src/global-settings/index.ts
667+
static async getMyServiceConfiguration(): Promise<MyServiceConfig | null> {
668+
const settings = await Promise.all([
669+
GlobalSettingsService.get('my-service.api_key'),
670+
GlobalSettingsService.get('my-service.enabled')
671+
]);
672+
673+
const [apiKey, enabled] = settings;
674+
675+
if (enabled?.value !== 'true' || !apiKey?.value) {
676+
return null;
677+
}
678+
679+
return {
680+
apiKey: apiKey.value,
681+
enabled: enabled.value === 'true'
682+
};
683+
}
684+
```
685+
686+
### Validation and Health Checks
687+
688+
The system provides validation for required settings:
689+
690+
```typescript
691+
// Check all required settings
692+
const validation = await GlobalSettingsInitService.validateRequiredSettings();
693+
694+
if (!validation.valid) {
695+
console.log('Missing required settings:', validation.missing);
696+
697+
// Check by category
698+
for (const [category, info] of Object.entries(validation.categories)) {
699+
if (info.missing > 0) {
700+
console.log(`${category}: ${info.missing}/${info.total} missing`);
701+
console.log('Missing keys:', info.missingKeys);
702+
}
703+
}
704+
}
705+
```
706+
707+
### Best Practices for Setting Definitions
708+
709+
- **Use Clear Keys**: Follow the `category.subcategory.setting` pattern
710+
- **Provide Descriptions**: Include helpful descriptions for administrators
711+
- **Mark Sensitive Data**: Set `encrypted: true` for passwords, API keys, secrets
712+
- **Set Appropriate Defaults**: Use sensible default values when possible
713+
- **Mark Required Settings**: Set `required: true` for essential settings
714+
- **Group Related Settings**: Use consistent category names
715+
716+
### Non-Destructive Behavior
717+
718+
The auto-initialization system is **completely non-destructive**:
719+
720+
-**Preserves existing settings**: Never overwrites existing values
721+
-**Only creates missing settings**: Skips settings that already exist
722+
-**Maintains user configurations**: Respects administrator changes
723+
-**Safe to run repeatedly**: Can be run multiple times without issues
724+
-**Logs all actions**: Transparent about what was created vs. skipped
725+
490726
## Future Enhancements
491727

492728
### Planned Features
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import type { GlobalSettingsModule } from './types';
2+
3+
export const githubOAuthSettings: GlobalSettingsModule = {
4+
category: 'github-oauth',
5+
settings: [
6+
{
7+
key: 'github.oauth.client_id',
8+
defaultValue: '',
9+
description: 'GitHub OAuth application client ID',
10+
encrypted: false,
11+
required: false
12+
},
13+
{
14+
key: 'github.oauth.client_secret',
15+
defaultValue: '',
16+
description: 'GitHub OAuth application client secret',
17+
encrypted: true,
18+
required: false
19+
},
20+
{
21+
key: 'github.oauth.enabled',
22+
defaultValue: 'false',
23+
description: 'Enable GitHub OAuth authentication (true/false)',
24+
encrypted: false,
25+
required: false
26+
},
27+
{
28+
key: 'github.oauth.callback_url',
29+
defaultValue: 'http://localhost:3000/api/auth/github/callback',
30+
description: 'GitHub OAuth callback URL',
31+
encrypted: false,
32+
required: false
33+
},
34+
{
35+
key: 'github.oauth.scope',
36+
defaultValue: 'user:email',
37+
description: 'GitHub OAuth requested scopes',
38+
encrypted: false,
39+
required: false
40+
}
41+
]
42+
};

0 commit comments

Comments
 (0)