1#![deny(unused_extern_crates)]
5#![forbid(unsafe_code)]
6
7#[cfg(feature = "host-only")]
8extern crate self as ft_sys_shared;
9
10mod email;
11mod sqlite;
12
13#[cfg(feature = "host-only")]
14pub use email::EmailBind;
15pub use email::{
16 CancelEmailError, Email, EmailAddress, EmailContent, EmailHandle, RenderedEmail, SendEmailError,
17};
18pub use sqlite::{SqliteRawValue, SqliteType};
19
20pub const SESSION_KEY: &str = "fastn-sid";
21pub const TRACKER_KEY: &str = "fastn-tid";
22
23#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
26pub struct Request {
27 pub uri: String,
28 pub method: String,
29 pub headers: Vec<(String, Vec<u8>)>,
30 pub body: Vec<u8>,
31}
32
33impl Request {
34 pub fn server_error(msg: String) -> Self {
35 Request {
36 uri: "server-error".to_string(),
37 method: "500".to_string(),
38 headers: vec![],
39 body: msg.into_bytes(),
40 }
41 }
42
43 pub fn host(&self) -> Option<&str> {
44 self.headers
45 .iter()
46 .find(|(k, _)| k.eq_ignore_ascii_case("host"))
47 .map(|(_, v)| std::str::from_utf8(v).unwrap())
48 }
49}
50
51impl From<Request> for http::Request<bytes::Bytes> {
52 fn from(r: Request) -> Self {
53 let mut req = http::Request::builder()
54 .method(r.method.as_str())
55 .uri(r.uri.as_str());
56
57 for (k, v) in r.headers {
58 req = req.header(k, v);
59 }
60
61 req.body(r.body.into()).unwrap()
62 }
63}
64
65impl From<Request> for http::Response<bytes::Bytes> {
66 fn from(r: Request) -> Self {
67 let mut req = http::Response::builder().status(r.method.parse::<u16>().unwrap());
68
69 for (k, v) in r.headers {
70 req = req.header(k, v);
71 }
72
73 req.body(r.body.into()).unwrap()
74 }
75}
76
77impl From<http::Request<bytes::Bytes>> for Request {
78 fn from(r: http::Request<bytes::Bytes>) -> Self {
79 let uri = r.uri().to_string();
80 let method = r.method().to_string();
81 let (parts, body) = r.into_parts();
82 let headers = parts
83 .headers
84 .iter()
85 .map(|(k, v)| (k.as_str().to_string(), v.as_bytes().to_vec()))
86 .collect();
87
88 Request {
89 uri,
90 method,
91 headers,
92 body: body.to_vec(),
93 }
94 }
95}
96
97impl From<http::Response<bytes::Bytes>> for Request {
98 fn from(r: http::Response<bytes::Bytes>) -> Self {
99 let (parts, body) = r.into_parts();
100 let headers = parts
101 .headers
102 .iter()
103 .map(|(k, v)| (k.as_str().to_string(), v.as_bytes().to_vec()))
104 .collect();
105
106 Request {
107 uri: "response-has-no-url".to_string(),
108 method: parts.status.as_str().to_string(),
109 headers,
110 body: body.to_vec(),
111 }
112 }
113}
114
115#[derive(Debug, serde::Deserialize, serde::Serialize, thiserror::Error)]
117pub enum DecryptionError {
118 #[error("Decryption failed: {0}")]
120 Generic(String),
121}
122
123#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
124#[serde(rename_all = "kebab-case")]
125pub struct UserData {
126 pub id: i64,
127 pub identity: String,
128 pub name: String,
129 pub email: String,
130 pub verified_email: bool,
131}
132
133#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
135pub enum DatabaseErrorKind {
136 UniqueViolation,
137 ForeignKeyViolation,
138 NotNullViolation,
139 CheckViolation,
140 SerializationFailure,
141 ReadOnlyTransaction,
142 ClosedConnection,
143 Unknown,
144}
145
146#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
147pub enum DbError {
148 DatabaseError {
149 kind: DatabaseErrorKind,
150 message: String,
151 details: Option<String>,
152 hint: Option<String>,
153 table_name: Option<String>,
154 column_name: Option<String>,
155 constraint_name: Option<String>,
156 statement_position: Option<i32>,
157 },
158 UnableToSendCommand(String),
159}