1#[cfg(not(feature = "auth"))]
2use crate::hashing::sha256_prefixed;
3#[cfg(not(feature = "auth"))]
4use crate::{PrayError, PrayResult};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct AuthRegistrationRequest {
9 pub email: String,
10}
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct AuthVerificationRequest {
14 pub email: String,
15 pub code: String,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub struct AuthSessionRequest {
20 pub email: String,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
24pub struct AuthPasskeyEnrollmentRequest {
25 pub email: String,
26 pub credential_id: String,
27 pub public_key: String,
28 #[serde(default)]
29 pub label: Option<String>,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
33pub struct AuthPasskeyChallengeRequest {
34 pub credential_id: String,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
38pub struct AuthPasskeyChallengeResponse {
39 pub credential_id: String,
40 pub challenge_id: String,
41 pub challenge: String,
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45pub struct AuthPasskeyLoginRequest {
46 pub credential_id: String,
47 pub challenge_id: String,
48 pub signature: String,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
52pub struct AuthSshKeyEnrollmentRequest {
53 pub email: String,
54 pub public_key: String,
55 #[serde(default)]
56 pub label: Option<String>,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
60pub struct AuthSshKeyChallengeRequest {
61 pub public_key: String,
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
65pub struct AuthSshKeyChallengeResponse {
66 pub fingerprint: String,
67 pub challenge_id: String,
68 pub challenge: String,
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
72pub struct AuthSshKeyLoginRequest {
73 pub public_key: String,
74 pub challenge_id: String,
75 pub signature: String,
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
79pub struct AuthRegistrationResponse {
80 pub email: String,
81 pub verified: bool,
82 #[serde(default)]
83 pub verification_code: Option<String>,
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
87pub struct AuthVerificationResponse {
88 pub email: String,
89 pub verified: bool,
90 pub token: String,
91 pub kind: AuthSessionKind,
92}
93
94#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
95#[serde(rename_all = "snake_case")]
96pub enum AuthSessionKind {
97 Email,
98 Passkey,
99 SshKey,
100}
101
102#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
103pub struct AuthSessionResponse {
104 pub email: String,
105 pub token: String,
106 pub kind: AuthSessionKind,
107}
108
109#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
110pub struct AuthPasskeyEnrollmentResponse {
111 pub email: String,
112 pub credential_id: String,
113 pub enrolled: bool,
114}
115
116#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
117pub struct AuthPasskeyLoginResponse {
118 pub email: String,
119 pub token: String,
120}
121
122#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
123pub struct AuthChallengeResponse {
124 pub challenge_id: String,
125 pub challenge: String,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
129pub struct AuthSshKeyEnrollmentResponse {
130 pub email: String,
131 pub fingerprint: String,
132 pub enrolled: bool,
133}
134
135#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
136pub struct AuthSshKeyLoginResponse {
137 pub email: String,
138 pub token: String,
139}
140
141#[cfg(feature = "auth")]
142pub use crate::auth_store::{
143 bearer_token_from_authorization, ssh_public_key_fingerprint_text, PublishTokenRecord,
144 RegistryAuthStore, PUBLISH_SCOPE,
145};
146
147#[cfg(not(feature = "auth"))]
148pub fn ssh_public_key_fingerprint_text(public_key: &str) -> PrayResult<String> {
149 let mut fields = public_key.split_whitespace();
150 let algorithm = fields.next().ok_or_else(|| PrayError::Parse {
151 kind: "public key",
152 message: "public key must include an algorithm".to_string(),
153 })?;
154 let encoded_key = fields.next().ok_or_else(|| PrayError::Parse {
155 kind: "public key",
156 message: "public key must include key bytes".to_string(),
157 })?;
158 if algorithm != "ssh-ed25519" {
159 return Err(PrayError::Unsupported(format!(
160 "unsupported public key algorithm: {algorithm}"
161 )));
162 }
163
164 Ok(sha256_prefixed(format!("{algorithm} {encoded_key}").as_bytes()).to_ascii_uppercase())
165}