feat: admin controls
This commit is contained in:
@@ -5,7 +5,7 @@ import { base64ToUint8Array, decrypt, deriveKey, encryptData, uint8ArrayToBase64
|
||||
const emit = defineEmits(['confirm', 'cancel']);
|
||||
|
||||
const { user } = useAuth();
|
||||
const { providers } = await useModels();
|
||||
const { providers, refresh } = await useModels();
|
||||
|
||||
const INPUT_CLASS = 'w-full h-9 px-2.5 text-sm rounded-md bg-[var(--bg-container)] placeholder:text-[var(--text-tertiary)]';
|
||||
|
||||
@@ -45,18 +45,19 @@ const importKey = (jwk: JsonWebKey) =>
|
||||
// one. The server never sees the plaintext keys.
|
||||
const decryptProviderKeys = async (
|
||||
oldJwk: JsonWebKey,
|
||||
): Promise<Result<{ id: string; plaintext: string }[], string[]>> => {
|
||||
): Promise<Result<{ id: string; originalApiKey: string; plaintext: string }[], string[]>> => {
|
||||
const oldKey = await importKey(oldJwk);
|
||||
|
||||
const decrypted: { id: string; plaintext: string }[] = [];
|
||||
const decrypted: { id: string; originalApiKey: string; plaintext: string }[] = [];
|
||||
const failed: string[] = [];
|
||||
|
||||
for (const provider of providers.value) {
|
||||
if (!provider.config.apiKey) continue;
|
||||
|
||||
try {
|
||||
const plaintext = await decrypt(oldKey, base64ToUint8Array(provider.config.apiKey));
|
||||
decrypted.push({ id: provider.id, plaintext });
|
||||
const originalApiKey = provider.config.apiKey;
|
||||
const plaintext = await decrypt(oldKey, base64ToUint8Array(originalApiKey));
|
||||
decrypted.push({ id: provider.id, originalApiKey, plaintext });
|
||||
} catch {
|
||||
failed.push(provider.name);
|
||||
}
|
||||
@@ -101,9 +102,9 @@ const submit = async () => {
|
||||
steps[1]!.state = 'active';
|
||||
const newJwk = await deriveKey(form.next, userId);
|
||||
const newKey = await importKey(newJwk);
|
||||
const providerKeys: { id: string; apiKey: string }[] = [];
|
||||
for (const { id, plaintext } of decrypted.data) {
|
||||
providerKeys.push({ id, apiKey: uint8ArrayToBase64(await encryptData(newKey, plaintext)) });
|
||||
const providerKeys: { id: string; originalApiKey: string; apiKey: string }[] = [];
|
||||
for (const { id, originalApiKey, plaintext } of decrypted.data) {
|
||||
providerKeys.push({ id, originalApiKey, apiKey: uint8ArrayToBase64(await encryptData(newKey, plaintext)) });
|
||||
}
|
||||
steps[1]!.state = 'done';
|
||||
|
||||
@@ -142,10 +143,7 @@ const submit = async () => {
|
||||
// from here on this browser has to use the new key
|
||||
localStorage.setItem('encryptionKey', JSON.stringify(newJwk));
|
||||
|
||||
const newKeys = new Map(providerKeys.map(p => [p.id, p.apiKey]));
|
||||
providers.value = providers.value.map(p =>
|
||||
newKeys.has(p.id) ? { ...p, config: { ...p.config, apiKey: newKeys.get(p.id)! } } : p
|
||||
);
|
||||
await refresh();
|
||||
|
||||
// the server signs the other devices out as part of the same request
|
||||
steps[2]!.state = 'done';
|
||||
|
||||
Reference in New Issue
Block a user