Merge pull request #4288 from gitbutlerapp/remove-unused-keys-mod

remove unused keys module
This commit is contained in:
Kiril Videlov 2024-07-09 00:39:40 +02:00 committed by GitHub
commit e89cd04c31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 2 additions and 330 deletions

View File

@ -41,8 +41,4 @@ export class AuthService {
if (resp) throw new Error(resp);
return { name: 'push', ok: true };
}
async getPublicKey() {
return await invoke<string>('get_public_key');
}
}

View File

@ -1,23 +1,16 @@
<script lang="ts">
import { AuthService } from '$lib/backend/auth';
import { GitConfigService } from '$lib/backend/gitConfigService';
import SectionCard from '$lib/components/SectionCard.svelte';
import ContentWrapper from '$lib/settings/ContentWrapper.svelte';
import Button from '$lib/shared/Button.svelte';
import Link from '$lib/shared/Link.svelte';
import Spacer from '$lib/shared/Spacer.svelte';
import TextBox from '$lib/shared/TextBox.svelte';
import Toggle from '$lib/shared/Toggle.svelte';
import { copyToClipboard } from '$lib/utils/clipboard';
import { getContext } from '$lib/utils/context';
import { openExternalUrl } from '$lib/utils/url';
import { onMount } from 'svelte';
const gitConfig = getContext(GitConfigService);
const authService = getContext(AuthService);
let annotateCommits = true;
let sshKey = '';
function toggleCommitterSigning() {
annotateCommits = !annotateCommits;
@ -25,7 +18,6 @@
}
onMount(async () => {
sshKey = await authService.getPublicKey();
annotateCommits = (await gitConfig.get('gitbutler.gitbutlerCommitter')) === '1';
});
</script>
@ -50,29 +42,4 @@
</SectionCard>
<Spacer />
<SectionCard>
<svelte:fragment slot="title">SSH key</svelte:fragment>
<svelte:fragment slot="caption">
GitButler uses SSH keys to authenticate with your Git provider. Add the following public key
to your Git provider to enable GitButler to push code.
</svelte:fragment>
<TextBox readonly selectall bind:value={sshKey} />
<div class="row-buttons">
<Button style="pop" kind="solid" icon="copy" on:click={() => copyToClipboard(sshKey)}>
Copy to clipboard
</Button>
<Button
style="ghost"
outline
icon="open-link"
on:mousedown={() => {
openExternalUrl('https://github.com/settings/ssh/new');
}}
>
Add key to GitHub
</Button>
</div>
</SectionCard>
</ContentWrapper>

View File

@ -1,29 +0,0 @@
use anyhow::Context;
use std::path::PathBuf;
use super::{storage::Storage, PrivateKey};
#[derive(Clone)]
pub struct Controller {
storage: Storage,
}
impl Controller {
pub fn new(storage: Storage) -> Self {
Self { storage }
}
pub fn from_path(path: impl Into<PathBuf>) -> Self {
Self::new(Storage::from_path(path))
}
pub fn get_or_create(&self) -> anyhow::Result<PrivateKey> {
if let Some(key) = self.storage.get().context("failed to get key")? {
Ok(key)
} else {
let key = PrivateKey::generate();
self.storage.create(&key).context("failed to save key")?;
Ok(key)
}
}
}

View File

@ -1,120 +0,0 @@
use std::{fmt, str::FromStr};
use rand::rngs::OsRng;
use serde::{Deserialize, Serialize};
use ssh_key::{HashAlg, LineEnding, SshSig};
#[derive(Debug, Clone, Eq)]
pub struct PrivateKey(ssh_key::PrivateKey);
impl PrivateKey {
pub fn generate() -> Self {
Self::default()
}
pub fn public_key(&self) -> PublicKey {
PublicKey::from(self)
}
pub fn sign(&self, bytes: &[u8]) -> anyhow::Result<String> {
let sig = SshSig::sign(&self.0, "git", HashAlg::Sha512, bytes)?;
sig.to_pem(LineEnding::default()).map_err(Into::into)
}
}
impl Default for PrivateKey {
fn default() -> Self {
let ed25519_keypair = ssh_key::private::Ed25519Keypair::random(&mut OsRng);
let ed25519_key = ssh_key::PrivateKey::from(ed25519_keypair);
Self(ed25519_key)
}
}
impl PartialEq for PrivateKey {
fn eq(&self, other: &Self) -> bool {
self.0.to_bytes().eq(&other.0.to_bytes())
}
}
impl Serialize for PrivateKey {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.to_string().serialize(serializer)
}
}
impl FromStr for PrivateKey {
type Err = ssh_key::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let key = ssh_key::PrivateKey::from_openssh(s.as_bytes())?;
Ok(Self(key))
}
}
impl fmt::Display for PrivateKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0
.to_openssh(ssh_key::LineEnding::default())
.map_err(|_| fmt::Error)?
.fmt(f)
}
}
impl<'de> Deserialize<'de> for PrivateKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Self::from_str(&s).map_err(serde::de::Error::custom)
}
}
#[derive(Debug)]
pub struct PublicKey(ssh_key::PublicKey);
impl From<&PrivateKey> for PublicKey {
fn from(value: &PrivateKey) -> Self {
Self(value.0.public_key().clone())
}
}
impl PartialEq for PublicKey {
fn eq(&self, other: &Self) -> bool {
self.0.to_bytes().eq(&other.0.to_bytes())
}
}
impl fmt::Display for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.to_openssh().map_err(|_| fmt::Error)?.fmt(f)
}
}
impl FromStr for PublicKey {
type Err = ssh_key::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let key = ssh_key::PublicKey::from_openssh(s)?;
Ok(Self(key))
}
}
impl Serialize for PublicKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.to_string().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for PublicKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Self::from_str(s.as_str()).map_err(serde::de::Error::custom)
}
}

View File

@ -1,6 +0,0 @@
pub mod controller;
mod key;
pub mod storage;
pub use controller::*;
pub use key::{PrivateKey, PublicKey};

View File

@ -1,33 +0,0 @@
use super::PrivateKey;
use crate::storage;
use anyhow::Result;
use std::path::PathBuf;
// TODO(ST): get rid of this type, it's more trouble than it's worth.
#[derive(Clone)]
pub struct Storage {
inner: storage::Storage,
}
impl Storage {
pub fn new(storage: storage::Storage) -> Storage {
Storage { inner: storage }
}
pub fn from_path(path: impl Into<PathBuf>) -> Storage {
Storage::new(storage::Storage::new(path))
}
pub fn get(&self) -> Result<Option<PrivateKey>> {
let key = self.inner.read("keys/ed25519")?;
key.map(|s| s.parse().map_err(Into::into)).transpose()
}
// TODO(ST): see if Key should rather deal with bytes instead for this kind of serialization.
pub fn create(&self, key: &PrivateKey) -> Result<()> {
self.inner.write("keys/ed25519", &key.to_string())?;
self.inner
.write("keys/ed25519.pub", &key.public_key().to_string())?;
Ok(())
}
}

View File

@ -18,7 +18,6 @@ pub mod error;
pub mod fs;
pub mod git;
pub mod id;
pub mod keys;
pub mod lock;
pub mod path;
pub mod secret;

View File

@ -1,3 +1,2 @@
mod keys;
mod lock;
mod types;

View File

@ -1,65 +0,0 @@
use gitbutler_core::keys::{PrivateKey, PublicKey};
mod controller {
#[cfg(not(target_os = "windows"))]
mod not_windows {
use std::fs;
#[cfg(target_family = "unix")]
use std::os::unix::prelude::*;
use gitbutler_core::keys::{storage::Storage, Controller};
use gitbutler_testsupport::Suite;
#[test]
fn get_or_create() {
let suite = Suite::default();
let controller = Controller::new(Storage::from_path(suite.local_app_data()));
let once = controller.get_or_create().unwrap();
let twice = controller.get_or_create().unwrap();
assert_eq!(once, twice);
// check permissions of the private key
let permissions = fs::metadata(suite.local_app_data().join("keys/ed25519"))
.unwrap()
.permissions();
let perms = format!("{:o}", permissions.mode());
assert_eq!(perms, "100600");
}
}
}
#[test]
fn to_from_string_private() {
let private_key = PrivateKey::generate();
let serialized = private_key.to_string();
let deserialized: PrivateKey = serialized.parse().unwrap();
assert_eq!(private_key, deserialized);
}
#[test]
fn to_from_string_public() {
let private_key = PrivateKey::generate();
let public_key = private_key.public_key();
let serialized = public_key.to_string();
let deserialized: PublicKey = serialized.parse().unwrap();
assert_eq!(public_key, deserialized);
}
#[test]
fn serde_private() {
let private_key = PrivateKey::generate();
let serialized = serde_json::to_string(&private_key).unwrap();
let deserialized: PrivateKey = serde_json::from_str(&serialized).unwrap();
assert_eq!(private_key, deserialized);
}
#[test]
fn serde_public() {
let private_key = PrivateKey::generate();
let public_key = private_key.public_key();
let serialized = serde_json::to_string(&public_key).unwrap();
let deserialized: PublicKey = serde_json::from_str(&serialized).unwrap();
assert_eq!(public_key, deserialized);
}

View File

@ -4,7 +4,6 @@ use std::{path::PathBuf, vec};
use anyhow::Context;
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::keys;
use gitbutler_core::git::Url;
use gitbutler_project::AuthKey;
@ -15,7 +14,6 @@ pub enum SshCredential {
key_path: PathBuf,
passphrase: Option<String>,
},
GitButlerKey(Box<keys::PrivateKey>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
@ -51,12 +49,6 @@ impl From<Credential> for git2::RemoteCallbacks<'_> {
git2::Cred::ssh_key("git", None, &key_path, passphrase.as_deref())
});
}
Credential::Ssh(SshCredential::GitButlerKey(key)) => {
remote_callbacks.credentials(move |url, _username_from_url, _allowed_types| {
tracing::info!("authenticating with {} using gitbutler's key", url);
git2::Cred::ssh_key_from_memory("git", None, &key.to_string(), None)
});
}
Credential::Https(HttpsCredential::CredentialHelper { username, password }) => {
remote_callbacks.credentials(move |url, _username_from_url, _allowed_types| {
tracing::info!("authenticating with {url} as '{username}' with password using credential helper");

View File

@ -1,17 +0,0 @@
pub mod commands {
use gitbutler_core::keys::{controller, PublicKey};
use tauri::Manager;
use tracing::instrument;
use crate::error::Error;
#[tauri::command(async)]
#[instrument(skip(handle), err(Debug))]
pub async fn get_public_key(handle: tauri::AppHandle) -> Result<PublicKey, Error> {
handle
.state::<controller::Controller>()
.get_or_create()
.map(|key| key.public_key())
.map_err(Into::into)
}
}

View File

@ -24,7 +24,6 @@ pub mod askpass;
pub mod config;
pub mod error;
pub mod github;
pub mod keys;
pub mod projects;
pub mod remotes;
pub mod repo;

View File

@ -16,8 +16,8 @@
use gitbutler_core::storage;
use gitbutler_repo::credentials::Helper;
use gitbutler_tauri::{
app, askpass, commands, config, github, keys, logs, menu, projects, remotes, repo, secret,
undo, users, virtual_branches, watcher, zip,
app, askpass, commands, config, github, logs, menu, projects, remotes, repo, secret, undo,
users, virtual_branches, watcher, zip,
};
use gitbutler_virtual::assets;
use tauri::{generate_context, Manager};
@ -128,12 +128,6 @@ fn main() {
app_handle.manage(gitbutler_feedback::controller::Controller::new(app_data_dir.clone(), app_log_dir.clone(), zipper.clone(), projects_controller.clone()));
let keys_storage_controller = gitbutler_core::keys::storage::Storage::new(storage_controller.clone());
app_handle.manage(keys_storage_controller.clone());
let keys_controller = gitbutler_core::keys::Controller::new(keys_storage_controller.clone());
app_handle.manage(keys_controller.clone());
let git_credentials_controller = Helper::default();
app_handle.manage(git_credentials_controller.clone());
@ -215,7 +209,6 @@ fn main() {
config::set_gb_config,
menu::menu_item_set_enabled,
menu::resolve_vscode_variant,
keys::commands::get_public_key,
github::commands::init_device_oauth,
github::commands::check_auth_status,
askpass::commands::submit_prompt_response,

View File

@ -15,7 +15,6 @@ pub struct Suite {
pub storage: gitbutler_core::storage::Storage,
pub users: gitbutler_user::Controller,
pub projects: gitbutler_project::Controller,
pub keys: gitbutler_core::keys::Controller,
}
impl Drop for Suite {
@ -32,13 +31,11 @@ impl Default for Suite {
let storage = gitbutler_core::storage::Storage::new(local_app_data.path());
let users = gitbutler_user::Controller::from_path(local_app_data.path());
let projects = gitbutler_project::Controller::from_path(local_app_data.path());
let keys = gitbutler_core::keys::Controller::from_path(local_app_data.path());
Self {
storage,
local_app_data: Some(local_app_data),
users,
projects,
keys,
}
}
}