Add pull request and repository browsing
This commit is contained in:
100
crates/app/src/storage.rs
Normal file
100
crates/app/src/storage.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
use std::{env, fs, path::PathBuf};
|
||||
|
||||
use gotcha_gitea::Client;
|
||||
use security_framework::passwords::{get_generic_password, set_generic_password};
|
||||
|
||||
use crate::domain::{Preferences, Server, open_status};
|
||||
|
||||
pub fn favorite_key(server: &str, owner: &str, repository: &str) -> String {
|
||||
format!("{server}|{owner}/{repository}")
|
||||
}
|
||||
|
||||
pub fn validate_server(name: &str, url: &str, token: &str) -> Result<Server, String> {
|
||||
let name = name.trim();
|
||||
let url = url.trim().trim_end_matches('/');
|
||||
let token = token.trim();
|
||||
if name.is_empty() {
|
||||
return Err("Give this server a name.".into());
|
||||
}
|
||||
if token.is_empty() {
|
||||
return Err("Enter an access token.".into());
|
||||
}
|
||||
Client::new(url, Some(token)).map_err(|error| error.to_string())?;
|
||||
Ok(Server {
|
||||
name: name.into(),
|
||||
url: url.into(),
|
||||
token: token.into(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn load_preferences() -> Result<Preferences, String> {
|
||||
let path = preferences_path()?;
|
||||
if !path.exists() {
|
||||
return Ok(Preferences::default());
|
||||
}
|
||||
let mut preferences: Preferences =
|
||||
serde_json::from_slice(&fs::read(&path).map_err(|error| error.to_string())?)
|
||||
.map_err(|error| format!("Cannot read {}: {error}", path.display()))?;
|
||||
if !matches!(preferences.issue_status.as_str(), "open" | "closed") {
|
||||
preferences.issue_status = open_status();
|
||||
}
|
||||
if !matches!(preferences.pull_status.as_str(), "open" | "closed") {
|
||||
preferences.pull_status = open_status();
|
||||
}
|
||||
for server in &mut preferences.servers {
|
||||
server.token = String::from_utf8(
|
||||
get_generic_password("de.rfc1437.gotcha", &keychain_account(server))
|
||||
.map_err(|error| format!("Cannot read the token for {}: {error}", server.name))?,
|
||||
)
|
||||
.map_err(|_| format!("The token for {} is not valid text.", server.name))?;
|
||||
}
|
||||
Ok(preferences)
|
||||
}
|
||||
|
||||
pub fn save_preferences(preferences: &Preferences) -> Result<(), String> {
|
||||
let path = preferences_path()?;
|
||||
let parent = path.parent().ok_or("Invalid app data directory.")?;
|
||||
fs::create_dir_all(parent).map_err(|error| error.to_string())?;
|
||||
let temporary = path.with_extension("tmp");
|
||||
fs::write(
|
||||
&temporary,
|
||||
serde_json::to_vec(preferences).map_err(|error| error.to_string())?,
|
||||
)
|
||||
.map_err(|error| error.to_string())?;
|
||||
fs::rename(&temporary, &path).map_err(|error| error.to_string())
|
||||
}
|
||||
|
||||
pub fn save_server_token(server: &Server) -> Result<(), String> {
|
||||
set_generic_password(
|
||||
"de.rfc1437.gotcha",
|
||||
&keychain_account(server),
|
||||
server.token.as_bytes(),
|
||||
)
|
||||
.map_err(|error| format!("Cannot save the token for {}: {error}", server.name))
|
||||
}
|
||||
|
||||
fn preferences_path() -> Result<PathBuf, String> {
|
||||
let home = env::var_os("HOME").ok_or("Cannot find the app data directory.")?;
|
||||
Ok(PathBuf::from(home).join("Library/Application Support/Gotcha/preferences.json"))
|
||||
}
|
||||
|
||||
fn keychain_account(server: &Server) -> String {
|
||||
format!("{}|{}", server.name, server.url)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn validates_servers_and_builds_stable_favorite_keys() {
|
||||
assert!(validate_server("Work", "https://gitea.example.com/", "secret").is_ok());
|
||||
assert!(validate_server("", "https://gitea.example.com", "secret").is_err());
|
||||
assert!(validate_server("Work", "file:///tmp/gitea", "secret").is_err());
|
||||
assert_eq!(
|
||||
favorite_key("https://gitea.example.com", "octo", "demo"),
|
||||
"https://gitea.example.com|octo/demo"
|
||||
);
|
||||
assert_eq!(Preferences::default().pull_status, "open");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user