assure SecretServices functions

- inject secretService so it works when used directly
- remove console logs
- only remove a migrated secret (instead of removing it unconditionally)
- in +template, await for good measure, which explains why the parent function is async

In the backend:
- prevent concurrency in method that stores secrets from the frontend
  as it's racy otherwise to type a secret quickly.
This commit is contained in:
Sebastian Thiel 2024-07-01 18:56:23 +02:00
parent 7f618fd248
commit b8da62c68b
No known key found for this signature in database
GPG Key ID: 9CB5EE7895E8268B
5 changed files with 9 additions and 5 deletions

View File

@ -20,11 +20,9 @@ export class RustSecretService implements SecretsService {
constructor(private gitConfigService: GitConfigService) {}
async get(handle: string) {
console.warn('getting ', handle);
const secret = await invoke<string>('secret_get_global', { handle });
if (secret) return secret;
console.warn('migrating', handle);
if (MIGRATION_HANDLES.includes(handle)) {
const key = 'gitbutler.' + handle;
const migratedSecret = await this.migrate(key, handle);
@ -48,7 +46,7 @@ export class RustSecretService implements SecretsService {
const secretInConfig = await this.gitConfigService.get(key);
if (secretInConfig === undefined) return;
this.set(handle, secretInConfig);
await this.set(handle, secretInConfig);
await this.gitConfigService.remove(key);
console.warn(`Migrated Git config "${key}" to secret store.`);

View File

@ -17,6 +17,7 @@
import { GitHubService } from '$lib/github/service';
import ToastController from '$lib/notifications/ToastController.svelte';
import { RemotesService } from '$lib/remotes/service';
import { setSecretsService } from '$lib/secrets/secretsService';
import { SETTINGS, loadUserSettings } from '$lib/settings/userSettings';
import { User, UserService } from '$lib/stores/user';
import * as events from '$lib/utils/events';
@ -36,6 +37,7 @@
setContext(SETTINGS, userSettings);
// Setters do not need to be reactive since `data` never updates
setSecretsService(data.secretsService);
setContext(UserService, data.userService);
setContext(ProjectService, data.projectService);
setContext(UpdaterService, data.updaterService);

View File

@ -75,6 +75,7 @@ export async function load() {
aiService,
remotesService,
aiPromptService,
lineManagerFactory
lineManagerFactory,
secretsService
};
}

View File

@ -43,7 +43,7 @@
async function setSecret(handle: AISecretHandle, secret: string | undefined) {
if (!initialized) return;
secretsService.set(handle, secret || '');
await secretsService.set(handle, secret || '');
}
$: setConfiguration(GitAIConfigKey.ModelProvider, modelKind);

View File

@ -1,6 +1,7 @@
use crate::error::Error;
use gitbutler_core::secret;
use gitbutler_core::types::Sensitive;
use std::sync::Mutex;
use tracing::instrument;
#[tauri::command(async)]
@ -12,6 +13,8 @@ pub async fn secret_get_global(handle: &str) -> Result<Option<String>, Error> {
#[tauri::command(async)]
#[instrument(skip(secret), err(Debug), fields(secret = "<redacted>"))]
pub async fn secret_set_global(handle: &str, secret: String) -> Result<(), Error> {
static FAIR_QUEUE: Mutex<()> = Mutex::new(());
let _one_at_a_time_to_prevent_races = FAIR_QUEUE.lock().unwrap();
Ok(secret::persist(
handle,
&Sensitive(secret),