movey_utils/
movey_credential.rs

1// Copyright (c) The Move Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4use anyhow::{bail, Context, Result};
5use std::fs;
6use toml_edit::easy::Value;
7
8#[cfg(debug_assertions)]
9pub const MOVEY_URL: &str = "https://movey-app-staging.herokuapp.com";
10#[cfg(not(debug_assertions))]
11pub const MOVEY_URL: &str = "https://www.movey.net";
12pub const MOVEY_CREDENTIAL_PATH: &str = "/movey_credential.toml";
13
14
15pub fn get_registry_api_token(move_home: &str) -> Result<String> {
16    if let Ok(content) = get_api_token(move_home) {
17        Ok(content)
18    } else {
19        bail!(
20            "There seems to be an error with your Movey API token. \
21            Please run `move movey-login` and follow the instructions."
22        )
23    }
24}
25
26pub fn get_api_token(move_home: &str) -> Result<String> {
27    let credential_path = format!("{}{}", move_home, MOVEY_CREDENTIAL_PATH);
28    let mut toml: Value = read_credential_file(&credential_path)?;
29    let token = get_registry_field(&mut toml, "token")?;
30    Ok(token.to_string().replace('\"', ""))
31}
32
33pub fn get_movey_url(move_home: &str) -> Result<String> {
34    let credential_path = format!("{}{}", move_home, MOVEY_CREDENTIAL_PATH);
35    let contents = fs::read_to_string(&credential_path)?;
36    let mut toml: Value = contents.parse()?;
37
38    let movey_url = get_registry_field(&mut toml, "url");
39   
40    if let Ok(url) = movey_url {
41        Ok(url.to_string().replace('\"', ""))
42    } else {
43        Ok(MOVEY_URL.to_string())
44    }
45}
46
47fn get_registry_field<'a>(toml: &'a mut Value, field: &'a str) -> Result<&'a mut Value> {
48    let registry = toml
49        .as_table_mut()
50        .context(format!("Error parsing {}", MOVEY_CREDENTIAL_PATH))?
51        .get_mut("registry")
52        .context(format!("Error parsing {}", MOVEY_CREDENTIAL_PATH))?;
53    let value = registry
54        .as_table_mut()
55        .context("Error parsing registry table")?
56        .get_mut(field)
57        .context("Error parsing token")?;
58    Ok(value)
59}
60
61pub fn read_credential_file(credential_path: &str) -> Result<Value> {
62    let content = match fs::read_to_string(credential_path) {
63        Ok(content) => content,
64        Err(error) => bail!("Error reading input: {}", error),
65    };
66    content.parse().map_err(|e| {
67        anyhow::Error::from(e).context(format!(
68            "could not parse input at {} as TOML",
69            &credential_path
70        ))
71    })
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use std::{env, fs::File};
78
79    fn setup_move_home(test_path: &str) -> (String, String) {
80        let cwd = env::current_dir().unwrap();
81        let mut move_home: String = String::from(cwd.to_string_lossy());
82        move_home.push_str(test_path);
83        let credential_path = move_home.clone() + MOVEY_CREDENTIAL_PATH;
84
85        (move_home, credential_path)
86    }
87
88    fn clean_up(move_home: &str) {
89        let _ = fs::remove_dir_all(move_home);
90    }
91
92    #[test]
93    fn get_api_token_works() {
94        let test_path = String::from("/get_api_token_works");
95        let (move_home, credential_path) = setup_move_home(&test_path);
96        let _ = fs::create_dir_all(&move_home);
97        File::create(&credential_path).unwrap();
98
99        let content = r#"
100            [registry]
101            token = "test-token"
102            "#;
103        fs::write(&credential_path, content).unwrap();
104
105        let token = get_registry_api_token(&move_home).unwrap();
106        assert!(token.contains("test-token"));
107
108        clean_up(&move_home)
109    }
110
111    #[test]
112    fn get_api_token_fails_if_there_is_no_move_home_directory() {
113        let test_path = String::from("/get_api_token_fails_if_there_is_no_move_home_directory");
114        let (move_home, _) = setup_move_home(&test_path);
115        let _ = fs::remove_dir_all(&move_home);
116
117        let token = get_registry_api_token(&move_home);
118        assert!(token.is_err());
119
120        clean_up(&move_home)
121    }
122
123    #[test]
124    fn get_api_token_fails_if_there_is_no_credential_file() {
125        let test_path = String::from("/get_api_token_fails_if_there_is_no_credential_file");
126        let (move_home, _) = setup_move_home(&test_path);
127        let _ = fs::remove_dir_all(&move_home);
128        fs::create_dir_all(&move_home).unwrap();
129
130        let token = get_registry_api_token(&move_home);
131        assert!(token.is_err());
132
133        clean_up(&move_home)
134    }
135
136    #[test]
137    fn get_api_token_fails_if_credential_file_is_in_wrong_format() {
138        let test_path = String::from("/get_api_token_fails_if_credential_file_is_in_wrong_format");
139        let (move_home, credential_path) = setup_move_home(&test_path);
140        let _ = fs::remove_dir_all(&move_home);
141        fs::create_dir_all(&move_home).unwrap();
142        File::create(&credential_path).unwrap();
143
144        let missing_double_quote = r#"
145            [registry]
146            token = test-token
147            "#;
148        fs::write(&credential_path, missing_double_quote).unwrap();
149        let token = get_registry_api_token(&move_home);
150        assert!(token.is_err());
151
152        let wrong_token_field = r#"
153            [registry]
154            tokens = "test-token"
155            "#;
156        fs::write(&credential_path, wrong_token_field).unwrap();
157        let token = get_registry_api_token(&move_home);
158        assert!(token.is_err());
159
160        clean_up(&move_home)
161    }
162
163    #[test]
164    fn get_movey_url_works() {
165        let test_path = String::from("/get_movey_url_works");
166        let (move_home, credential_path) = setup_move_home(&test_path);
167        let _ = fs::create_dir_all(&move_home);
168        File::create(&credential_path).unwrap();
169        let content = r#"
170            [registry]
171            token = "test-token"
172            url = "test-url"
173            "#;
174        fs::write(&credential_path, content).unwrap();
175
176        let url = get_movey_url(&move_home).unwrap();
177        assert_eq!(url, "test-url");
178
179        clean_up(&move_home)
180    }
181
182    #[test]
183    fn get_movey_url_returns_default_url_if_url_field_not_existed() {
184        let test_path = String::from("/get_movey_url_returns_default_url_if_url_field_not_existed");
185        let (move_home, credential_path) = setup_move_home(&test_path);
186        let _ = fs::create_dir_all(&move_home);
187        File::create(&credential_path).unwrap();
188        let content = r#"
189            [registry]
190            token = "test-token"
191            "#;
192        fs::write(&credential_path, content).unwrap();
193
194        let url = get_movey_url(&move_home).unwrap();
195        assert_eq!(url, MOVEY_URL);
196
197        clean_up(&move_home)
198    }
199}