Skip to content

Commit a20ab53

Browse files
committed
added external secrets manager interfaces
1 parent 757ca49 commit a20ab53

File tree

7 files changed

+101
-668
lines changed

7 files changed

+101
-668
lines changed
Lines changed: 0 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -1,206 +0,0 @@
1-
import { SecretProviderType } from "./providerService/types";
2-
3-
/**
4-
* Cached secret entry
5-
*/
6-
interface CachedSecret {
7-
value: string;
8-
providerId: string;
9-
providerType: SecretProviderType;
10-
secretName: string;
11-
fetchedAt: number;
12-
expiresAt: number;
13-
}
14-
15-
/**
16-
* TTL configuration per provider type
17-
*/
18-
const DEFAULT_TTL: Record<SecretProviderType, number> = {
19-
[SecretProviderType.AWS_SECRETS_MANGER]: 60 * 60 * 1000, // 60 minutes
20-
};
21-
22-
// Only 1 provider active at a time, so no need for complex strategies
23-
// name to value is enough
24-
25-
/**
26-
* In-memory cache for secrets
27-
* - Session-scoped (cleared on app restart)
28-
* - TTL-based expiration
29-
* - Provider-aware invalidation
30-
*/
31-
export class CacheService {
32-
private cache: Map<string, CachedSecret> = new Map();
33-
34-
get(secretName: string): string | null {
35-
const entry = this.cache.get(secretName);
36-
37-
if (!entry) {
38-
// provider.fetchSecret(secretName);
39-
//
40-
41-
}
42-
43-
// Check if expired
44-
if (Date.now() > entry.expiresAt) {
45-
this.cache.delete(secretName);
46-
return null;
47-
}
48-
49-
return entry.value;
50-
}
51-
52-
/**
53-
* Set a cached secret
54-
*/
55-
set(
56-
providerId: string,
57-
providerType: SecretProviderType,
58-
secretName: string,
59-
value: string,
60-
customTTL?: number
61-
): void {
62-
const key = this.getCacheKey(providerId, secretName);
63-
const ttl = customTTL ?? DEFAULT_TTL[providerType];
64-
const now = Date.now();
65-
66-
this.cache.set(key, {
67-
value,
68-
providerId,
69-
providerType,
70-
secretName,
71-
fetchedAt: now,
72-
expiresAt: ttl === Infinity ? Infinity : now + ttl,
73-
});
74-
}
75-
76-
/**
77-
* Invalidate a specific secret
78-
*/
79-
invalidate(providerId: string, secretName: string): boolean {
80-
const key = this.getCacheKey(providerId, secretName);
81-
return this.cache.delete(key);
82-
}
83-
84-
/**
85-
* Invalidate all secrets from a specific provider
86-
*/
87-
invalidateByProvider(providerId: string): number {
88-
let count = 0;
89-
90-
for (const [key, entry] of this.cache.entries()) {
91-
if (entry.providerId === providerId) {
92-
this.cache.delete(key);
93-
count++;
94-
}
95-
}
96-
97-
return count;
98-
}
99-
100-
/**
101-
* Invalidate all secrets of a specific provider type
102-
*/
103-
invalidateByProviderType(providerType: SecretProviderType): number {
104-
let count = 0;
105-
106-
for (const [key, entry] of this.cache.entries()) {
107-
if (entry.providerType === providerType) {
108-
this.cache.delete(key);
109-
count++;
110-
}
111-
}
112-
113-
return count;
114-
}
115-
116-
/**
117-
* Clear all cached secrets
118-
*/
119-
clear(): void {
120-
this.cache.clear();
121-
this.stats.hits = 0;
122-
this.stats.misses = 0;
123-
}
124-
125-
/**
126-
* Get cache statistics
127-
*/
128-
getStats(): CacheStats {
129-
const total = this.stats.hits + this.stats.misses;
130-
131-
return {
132-
size: this.cache.size,
133-
hits: this.stats.hits,
134-
misses: this.stats.misses,
135-
hitRate: total > 0 ? this.stats.hits / total : 0,
136-
};
137-
}
138-
139-
/**
140-
* Clean up expired entries
141-
* Should be called periodically
142-
*/
143-
cleanExpired(): number {
144-
let count = 0;
145-
const now = Date.now();
146-
147-
for (const [key, entry] of this.cache.entries()) {
148-
if (entry.expiresAt !== Infinity && now > entry.expiresAt) {
149-
this.cache.delete(key);
150-
count++;
151-
}
152-
}
153-
154-
return count;
155-
}
156-
157-
/**
158-
* Get all cached entries (for debugging)
159-
*/
160-
getAllEntries(): Array<{ key: string; entry: CachedSecret }> {
161-
return Array.from(this.cache.entries()).map(([key, entry]) => ({
162-
key,
163-
entry,
164-
}));
165-
}
166-
167-
/**
168-
* Check if a specific secret is cached and valid
169-
*/
170-
has(providerId: string, secretName: string): boolean {
171-
const key = this.getCacheKey(providerId, secretName);
172-
const entry = this.cache.get(key);
173-
174-
if (!entry) {
175-
return false;
176-
}
177-
178-
// Check if expired
179-
if (entry.expiresAt !== Infinity && Date.now() > entry.expiresAt) {
180-
this.cache.delete(key);
181-
return false;
182-
}
183-
184-
return true;
185-
}
186-
187-
/**
188-
* Get time until a cached secret expires (in ms)
189-
* Returns null if not cached or already expired
190-
*/
191-
getTimeToExpiry(providerId: string, secretName: string): number | null {
192-
const key = this.getCacheKey(providerId, secretName);
193-
const entry = this.cache.get(key);
194-
195-
if (!entry) {
196-
return null;
197-
}
198-
199-
if (entry.expiresAt === Infinity) {
200-
return Infinity;
201-
}
202-
203-
const remaining = entry.expiresAt - Date.now();
204-
return remaining > 0 ? remaining : null;
205-
}
206-
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { safeStorage } from "electron";
2+
3+
export class EncryptedFsStorageService {
4+
constructor(private readonly baseFolderPath: string) {
5+
}
6+
7+
async initialize(): Promise<void> {
8+
if (!safeStorage.isEncryptionAvailable()) {
9+
// Show trouble shooting steps to user
10+
throw new Error("Encryption is not available on this system. ");
11+
}
12+
13+
// initialize directories
14+
}
15+
16+
async save(
17+
data: Record<string, any>,
18+
path: string,
19+
keysToEncrypt: string[] = []
20+
): Promise<void> {
21+
// encrypted
22+
}
23+
24+
async load(
25+
path: string,
26+
keysToDecrypt: string[] = []
27+
): Promise< {
28+
29+
}
30+
31+
async delete(path: string): Promise<void> {
32+
33+
}
34+
}

src/main/actions/externalSecrets/encryptedStorageService.ts

Lines changed: 0 additions & 134 deletions
This file was deleted.

0 commit comments

Comments
 (0)