1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
4pub enum AuthLevel {
5 None,
6 Consumer,
7 User,
8}
9
10#[derive(Debug, Clone, Default)]
11pub enum Auth {
12 #[default]
13 None,
14 UserToken {
15 token: String,
16 },
17 Discogs {
18 consumer_key: String,
19 consumer_secret: String,
20 },
21 OAuth {
22 consumer_key: String,
23 consumer_secret: String,
24 access_token: String,
25 access_token_secret: String,
26 },
27}
28
29impl Auth {
30 pub fn level(&self) -> AuthLevel {
31 match self {
32 Auth::None => AuthLevel::None,
33 Auth::Discogs { .. } => AuthLevel::Consumer,
34 Auth::UserToken { .. } | Auth::OAuth { .. } => AuthLevel::User,
35 }
36 }
37
38 pub fn authorization_header(&self) -> Option<String> {
39 match self {
40 Auth::None => None,
41 Auth::UserToken { token } => Some(format!("Discogs token={token}")),
42 Auth::Discogs {
43 consumer_key,
44 consumer_secret,
45 } => Some(format!(
46 "Discogs key={consumer_key}, secret={consumer_secret}"
47 )),
48 Auth::OAuth {
49 consumer_key,
50 consumer_secret,
51 access_token,
52 access_token_secret,
53 } => Some(crate::oauth::build_oauth_header(
54 consumer_key,
55 consumer_secret,
56 access_token,
57 access_token_secret,
58 )),
59 }
60 }
61}
62
63#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default)]
64#[serde(rename_all = "snake_case")]
65pub enum OutputFormat {
66 #[default]
67 Discogs,
68 Plaintext,
69 Html,
70}
71
72impl OutputFormat {
73 pub fn accept_header_value(self) -> &'static str {
74 match self {
75 OutputFormat::Discogs => "application/vnd.discogs.v2.discogs+json",
76 OutputFormat::Plaintext => "application/vnd.discogs.v2.plaintext+json",
77 OutputFormat::Html => "application/vnd.discogs.v2.html+json",
78 }
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::{Auth, AuthLevel, OutputFormat};
85
86 #[test]
87 fn auth_levels_match_expected_capabilities() {
88 assert_eq!(Auth::None.level(), AuthLevel::None);
89 assert_eq!(
90 Auth::Discogs {
91 consumer_key: "k".into(),
92 consumer_secret: "s".into(),
93 }
94 .level(),
95 AuthLevel::Consumer
96 );
97 assert_eq!(
98 Auth::UserToken { token: "t".into() }.level(),
99 AuthLevel::User
100 );
101 }
102
103 #[test]
104 fn output_accept_header_is_stable() {
105 assert_eq!(
106 OutputFormat::Discogs.accept_header_value(),
107 "application/vnd.discogs.v2.discogs+json"
108 );
109 assert_eq!(
110 OutputFormat::Plaintext.accept_header_value(),
111 "application/vnd.discogs.v2.plaintext+json"
112 );
113 assert_eq!(
114 OutputFormat::Html.accept_header_value(),
115 "application/vnd.discogs.v2.html+json"
116 );
117 }
118
119 #[test]
120 fn user_token_auth_header_format_is_stable() {
121 let header = Auth::UserToken {
122 token: "abc123".into(),
123 }
124 .authorization_header()
125 .expect("header should exist");
126
127 assert_eq!(header, "Discogs token=abc123");
128 }
129}