use std::path::PathBuf;
+use std::io::Write;
+
+use std::fs::OpenOptions;
+
+#[cfg(unix)]
+use std::os::unix::fs::OpenOptionsExt;
#[cfg(windows)]
use std::str::FromStr;
pub fn get_path(&self, leaf: &str) -> PathBuf {
self.dir.join(leaf)
}
+
+ pub fn create_file(&self, leaf: &str, contents: &str) ->
+ Result<(), std::io::Error>
+ {
+ std::fs::create_dir_all(&self.dir)?;
+
+ // FIXME: we could do better here, by creating a file under a
+ // separate name and then atomically renaming it
+
+ let mut opts = OpenOptions::new();
+ opts.write(true);
+ opts.create_new(true);
+
+ // On Windows files are not-world-readable by default, but on
+ // Unix we must be careful about this
+ #[cfg(unix)]
+ opts.mode(0o600);
+
+ let path = self.get_path(leaf);
+ opts.open(path)?
+ .write_all(contents.as_bytes())
+ }
}
use reqwest::Url;
use std::io::Write;
-use super::auth::AuthConfig;
+use super::TopLevelError;
+use super::auth::{AuthConfig, AuthError};
+use super::config::ConfigLocation;
use super::client::{reqwest_client, Req, ClientError};
use super::types::{Account, Application, Instance, Token};
}
}
-pub fn login(instance_url: &str) -> Result<(), ClientError> {
+pub fn login(cfgloc: &ConfigLocation, instance_url: &str) ->
+ Result<(), TopLevelError>
+{
+ // First, check we aren't logged in already, and give some
+ // marginally useful advice on what to do if we are.
+ match AuthConfig::load(cfgloc) {
+ Err(AuthError::Nonexistent(..)) => Ok(()),
+ Ok(auth) => Err(TopLevelError::new("", &format!(
+ "you are already logged in as {0}@{1}! Use --config to specify a separate configuration directory for another login, or delete {2} to remove the existing login details",
+ auth.username, auth.instance_domain, cfgloc.get_path("auth").display()))),
+ Err(e) => Err(TopLevelError::from(e)),
+ }?;
+
// Ergonomics: parse the URL, adding a default https:// scheme if
// it's just a bare hostname
let urlstr = match instance_url.find('/') {
&user_token.access_token)?;
println!("");
- println!("Successfully logged in as {}@{}", account.id, instance.domain);
+ println!("Successfully logged in as {}@{}", account.username, instance.domain);
+ println!("Now run 'mastodonochrome' without arguments to read and post!");
// Save everything!
let auth = AuthConfig {
client_secret: app.client_secret.unwrap(),
user_token: user_token.access_token,
};
- println!("JSON: {}", serde_json::to_string_pretty(&auth).unwrap());
+
+ cfgloc.create_file("auth", &serde_json::to_string_pretty(&auth).unwrap())?;
Ok(())
}