gix_credentials/protocol/
mod.rs1use bstr::BString;
2
3use crate::helper;
4
5#[derive(Debug, Clone, Eq, PartialEq)]
7pub struct Outcome {
8 pub identity: gix_sec::identity::Account,
10 pub next: helper::NextAction,
12}
13
14pub type Result = std::result::Result<Option<Outcome>, Error>;
16
17#[derive(Debug, thiserror::Error)]
19#[allow(missing_docs)]
20pub enum Error {
21 #[error(transparent)]
22 UrlParse(#[from] gix_url::parse::Error),
23 #[error("Either 'url' field or both 'protocol' and 'host' fields must be provided")]
24 UrlMissing,
25 #[error(transparent)]
26 ContextDecode(#[from] context::decode::Error),
27 #[error(transparent)]
28 InvokeHelper(#[from] helper::Error),
29 #[error("Could not configure credential helpers")]
30 ConfigureCredentialHelpers {
31 #[source]
32 source: Box<dyn std::error::Error + Send + Sync + 'static>,
33 },
34 #[error("Could not obtain identity for context: {}", { let mut buf = Vec::<u8>::new(); context.write_to(&mut buf).ok(); String::from_utf8_lossy(&buf).into_owned() })]
35 IdentityMissing { context: Context },
36 #[error("The handler asked to stop trying to obtain credentials")]
37 Quit,
38 #[error("Couldn't obtain {prompt}")]
39 Prompt { prompt: String, source: gix_prompt::Error },
40}
41
42#[derive(Debug, Default, Clone, Eq, PartialEq)]
44pub struct Context {
45 pub protocol: Option<String>,
47 pub host: Option<String>,
49 pub path: Option<BString>,
52 pub username: Option<String>,
54 pub password: Option<String>,
56 pub oauth_refresh_token: Option<String>,
58 pub password_expiry_utc: Option<gix_date::SecondsSinceUnixEpoch>,
60 pub url: Option<BString>,
64 pub quit: Option<bool>,
66}
67
68#[allow(clippy::result_large_err)]
70pub fn helper_outcome_to_result(outcome: Option<helper::Outcome>, action: helper::Action) -> Result {
71 match (action, outcome) {
72 (helper::Action::Get(ctx), None) => Err(Error::IdentityMissing {
73 context: ctx.redacted(),
74 }),
75 (helper::Action::Get(ctx), Some(mut outcome)) => match outcome.consume_identity() {
76 Some(identity) => Ok(Some(Outcome {
77 identity,
78 next: outcome.next,
79 })),
80 None => Err(if outcome.quit {
81 Error::Quit
82 } else {
83 Error::IdentityMissing {
84 context: ctx.redacted(),
85 }
86 }),
87 },
88 (helper::Action::Store(_) | helper::Action::Erase(_), _ignore) => Ok(None),
89 }
90}
91
92pub mod context;