headless_lms_server/domain/oauth/
redirects.rs1use url::form_urlencoded;
2
3use crate::domain::oauth::authorize_query::AuthorizeParams;
4
5pub fn build_authorize_qs(q: &AuthorizeParams) -> String {
6 let mut s = form_urlencoded::Serializer::new(String::new());
7 s.append_pair("client_id", &q.client_id);
8 s.append_pair("scope", &q.scope);
9 s.append_pair("redirect_uri", &q.redirect_uri);
10 s.append_pair("response_type", &q.response_type);
11 if let Some(state) = q.state.as_deref() {
12 s.append_pair("state", state);
13 }
14 if let Some(nonce) = q.nonce.as_deref() {
15 s.append_pair("nonce", nonce);
16 }
17 if let Some(code_challenge) = q.code_challenge.as_deref() {
18 s.append_pair("code_challenge", code_challenge);
19 }
20 if let Some(code_challenge_method) = q.code_challenge_method.as_deref() {
21 s.append_pair("code_challenge_method", code_challenge_method);
22 }
23 s.finish()
24}
25
26pub fn pct_encode(s: &str) -> String {
27 form_urlencoded::byte_serialize(s.as_bytes()).collect()
28}
29
30pub fn build_login_redirect(q: &AuthorizeParams) -> String {
31 let return_to = format!(
32 "/api/v0/main-frontend/oauth/authorize?{}",
33 build_authorize_qs(q)
34 );
35 format!("/login?return_to={}", pct_encode(&return_to))
36}
37
38pub fn build_consent_redirect(q: &AuthorizeParams, return_to: &str) -> String {
39 format!(
40 "/oauth_authorize_scopes?{}&return_to={}",
41 build_authorize_qs(q),
42 pct_encode(return_to)
43 )
44}
45
46pub fn redirect_with_code(redirect_uri: &str, code: &str, state: Option<&str>) -> String {
47 let mut qs = form_urlencoded::Serializer::new(String::new());
48 qs.append_pair("code", code);
49 if let Some(s) = state {
50 qs.append_pair("state", s);
51 }
52 let qs = qs.finish();
53 if redirect_uri.contains('?') {
54 format!("{redirect_uri}&{qs}")
55 } else {
56 format!("{redirect_uri}?{qs}")
57 }
58}