1#![warn(missing_docs)]
6
7use std::borrow::Cow;
8
9use oxide_auth::endpoint::{OAuthError as EndpointError, QueryParameter, WebRequest, WebResponse};
10use oxide_auth::frontends::simple::endpoint::Error as SimpleError;
11
12use iron::{Request, Response};
13use iron::error::IronError;
14use iron::headers;
15use iron::status::Status;
16use url::Url;
17
18pub enum Error {
20 BadRequest,
22}
23
24#[derive(Debug)]
25pub struct OAuthRequest<'a, 'b, 'c: 'b>(&'a mut Request<'b, 'c>);
30
31#[derive(Debug)]
32pub struct OAuthResponse(Response);
37
38#[derive(Debug)]
39pub struct OAuthError(IronError);
41
42impl<'a, 'b, 'c: 'b> OAuthRequest<'a, 'b, 'c> {
43 pub fn from_request(request: &'a mut Request<'b, 'c>) -> Self {
45 OAuthRequest(request)
46 }
47
48 pub fn url(&self) -> &iron::url::Url {
50 self.0.url.as_ref()
51 }
52
53 pub fn query_string(&self) -> &str {
55 self.0.url.query().unwrap_or("")
56 }
57
58 pub fn is_form_url_encoded(&self) -> bool {
60 self.0
61 .headers
62 .get::<headers::ContentType>()
63 .map(|ct| ct == &headers::ContentType::form_url_encoded())
64 .unwrap_or(false)
65 }
66
67 pub fn authorization_header(&self) -> Option<Cow<str>> {
69 self.0
71 .headers
72 .get::<headers::Authorization<String>>()
73 .map(|h| Cow::Borrowed(h.0.as_ref()))
74 }
75}
76
77impl OAuthResponse {
78 pub fn new() -> Self {
80 OAuthResponse(Response::new())
81 }
82
83 pub fn from_response(response: Response) -> Self {
85 OAuthResponse(response)
86 }
87
88 pub fn set_status(&mut self, status: Status) {
90 self.0.status = Some(status);
91 }
92
93 pub fn set_header<H>(&mut self, header: H)
95 where
96 H: headers::HeaderFormat + headers::Header,
97 {
98 self.0.headers.set(header);
99 }
100
101 pub fn set_raw_header(&mut self, name: Cow<'static, str>, values: Vec<Vec<u8>>) {
103 self.0.headers.set_raw(name, values);
104 }
105
106 pub fn set_body(&mut self, body: &str) {
108 self.0.body = Some(Box::new(body.to_string()));
109 }
110}
111
112impl<'a, 'b, 'c: 'b> WebRequest for OAuthRequest<'a, 'b, 'c> {
114 type Response = OAuthResponse;
115 type Error = Error;
116
117 fn query(&mut self) -> Result<Cow<dyn QueryParameter + 'static>, Self::Error> {
118 serde_urlencoded::from_str(self.query_string())
119 .map_err(|_| Error::BadRequest)
120 .map(Cow::Owned)
121 }
122
123 fn urlbody(&mut self) -> Result<Cow<dyn QueryParameter + 'static>, Self::Error> {
124 let formatted = self.is_form_url_encoded();
125 if !formatted {
126 return Err(Error::BadRequest);
127 }
128
129 serde_urlencoded::from_reader(&mut self.0.body)
130 .map_err(|_| Error::BadRequest)
131 .map(Cow::Owned)
132 }
133
134 fn authheader(&mut self) -> Result<Option<Cow<str>>, Self::Error> {
135 Ok(self.authorization_header())
136 }
137}
138
139impl WebResponse for OAuthResponse {
140 type Error = Error;
141
142 fn ok(&mut self) -> Result<(), Self::Error> {
143 self.set_status(Status::Ok);
144 Ok(())
145 }
146
147 fn redirect(&mut self, url: Url) -> Result<(), Self::Error> {
148 self.set_status(Status::Found);
149 self.set_header(headers::Location(url.into()));
150 Ok(())
151 }
152
153 fn client_error(&mut self) -> Result<(), Self::Error> {
154 self.set_status(Status::BadRequest);
155 Ok(())
156 }
157
158 fn unauthorized(&mut self, header_value: &str) -> Result<(), Self::Error> {
159 self.set_status(Status::Unauthorized);
160 let value_owned = header_value.as_bytes().to_vec();
161 self.set_raw_header("WWW-Authenticate".into(), vec![value_owned]);
162 Ok(())
163 }
164
165 fn body_text(&mut self, text: &str) -> Result<(), Self::Error> {
166 self.set_header(headers::ContentType::plaintext());
167 self.set_body(text);
168 Ok(())
169 }
170
171 fn body_json(&mut self, data: &str) -> Result<(), Self::Error> {
172 self.set_header(headers::ContentType::json());
173 self.set_body(data);
174 Ok(())
175 }
176}
177
178impl<'a, 'b, 'c: 'b> From<&'a mut Request<'b, 'c>> for OAuthRequest<'a, 'b, 'c> {
179 fn from(r: &'a mut Request<'b, 'c>) -> Self {
180 OAuthRequest::from_request(r)
181 }
182}
183
184impl<'a, 'b, 'c: 'b> Into<&'a mut Request<'b, 'c>> for OAuthRequest<'a, 'b, 'c> {
185 fn into(self) -> &'a mut Request<'b, 'c> {
186 self.0
187 }
188}
189
190impl From<Response> for OAuthResponse {
191 fn from(r: Response) -> Self {
192 OAuthResponse::from_response(r)
193 }
194}
195
196impl Into<Response> for OAuthResponse {
197 fn into(self) -> Response {
198 self.0
199 }
200}
201
202impl<'a, 'b, 'c: 'b> From<SimpleError<OAuthRequest<'a, 'b, 'c>>> for OAuthError {
203 fn from(error: SimpleError<OAuthRequest<'a, 'b, 'c>>) -> Self {
204 let as_oauth = match error {
205 SimpleError::Web(Error::BadRequest) => EndpointError::BadRequest,
206 SimpleError::OAuth(oauth) => oauth,
207 };
208
209 let status = match as_oauth {
210 EndpointError::BadRequest => Status::BadRequest,
211 EndpointError::DenySilently => Status::BadRequest,
212 EndpointError::PrimitiveError => Status::InternalServerError,
213 };
214
215 OAuthError(IronError::new(as_oauth, status))
216 }
217}
218
219impl From<IronError> for OAuthError {
220 fn from(e: IronError) -> Self {
221 OAuthError(e)
222 }
223}
224
225impl Into<IronError> for OAuthError {
226 fn into(self) -> IronError {
227 self.0
228 }
229}