headless_lms_server/domain/oauth/
redirects.rs

1use 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}