[BE] Get session cookie from online classroom

master
Araozu 2023-09-22 12:03:25 -05:00
parent 73205c5622
commit 5992908ce6
7 changed files with 223 additions and 11 deletions

77
backend/Cargo.lock generated
View File

@ -237,6 +237,17 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
[[package]]
name = "cookie"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
dependencies = [
"percent-encoding",
"time 0.3.27",
"version_check",
]
[[package]] [[package]]
name = "cookie" name = "cookie"
version = "0.17.0" version = "0.17.0"
@ -248,6 +259,23 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "cookie_store"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d606d0fba62e13cf04db20536c05cb7f13673c161cb47a47a82b9b9e7d3f1daa"
dependencies = [
"cookie 0.16.2",
"idna 0.2.3",
"log",
"publicsuffix",
"serde",
"serde_derive",
"serde_json",
"time 0.3.27",
"url",
]
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.3" version = "0.9.3"
@ -828,6 +856,27 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "idna"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "idna"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.4.0" version = "0.4.0"
@ -984,6 +1033,12 @@ dependencies = [
"regex-automata 0.1.10", "regex-automata 0.1.10",
] ]
[[package]]
name = "matches"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]] [[package]]
name = "md-5" name = "md-5"
version = "0.10.5" version = "0.10.5"
@ -1366,6 +1421,22 @@ dependencies = [
"yansi 1.0.0-rc.1", "yansi 1.0.0-rc.1",
] ]
[[package]]
name = "psl-types"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac"
[[package]]
name = "publicsuffix"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457"
dependencies = [
"idna 0.3.0",
"psl-types",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.33" version = "1.0.33"
@ -1486,6 +1557,8 @@ checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
dependencies = [ dependencies = [
"base64", "base64",
"bytes", "bytes",
"cookie 0.16.2",
"cookie_store",
"encoding_rs", "encoding_rs",
"futures-core", "futures-core",
"futures-util", "futures-util",
@ -1615,7 +1688,7 @@ version = "0.5.0-rc.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936012c99162a03a67f37f9836d5f938f662e26f2717809761a9ac46432090f4" checksum = "936012c99162a03a67f37f9836d5f938f662e26f2717809761a9ac46432090f4"
dependencies = [ dependencies = [
"cookie", "cookie 0.17.0",
"either", "either",
"futures", "futures",
"http", "http",
@ -2552,7 +2625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"idna", "idna 0.4.0",
"percent-encoding", "percent-encoding",
] ]

View File

@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
reqwest = { version = "0.11", features = ["json"] } reqwest = { version = "0.11", features = ["json", "cookies"] }
rocket = { version = "=0.5.0-rc.3" , features = ["json", "msgpack", "uuid"] } rocket = { version = "=0.5.0-rc.3" , features = ["json", "msgpack", "uuid"] }
sqlx = { version = "0.7.1", features = [ "runtime-tokio", "tls-rustls", "mysql", "macros", "chrono" ] } sqlx = { version = "0.7.1", features = [ "runtime-tokio", "tls-rustls", "mysql", "macros", "chrono" ] }
once_cell = "1.18.0" once_cell = "1.18.0"

View File

@ -50,6 +50,10 @@ async fn rocket() -> _ {
controller::register::get_by_dni, controller::register::get_by_dni,
controller::register::delete, controller::register::delete,
controller::custom_label::get_all, controller::custom_label::get_all,
//
// Online classroom routes
//
online_classroom::connection,
], ],
) )
} }

View File

@ -1,6 +1,85 @@
use once_cell::sync::OnceCell;
pub fn get_cookie() { use reqwest::Client;
use rocket::{http::Status, serde::json::Json};
use serde::{Deserialize, Serialize};
static SESSION_COOKIE: OnceCell<String> = OnceCell::new();
#[derive(Debug, Serialize, Deserialize)]
pub enum ConnectionResult {
Ok(),
Error(ConnectionError),
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ConnectionError {
reason: String,
}
fn new_error(reason: String) -> ConnectionResult {
ConnectionResult::Error(ConnectionError { reason })
} }
/// Tries to connect to the online classroom, and get a session cookie
#[get("/classroom/connect")]
pub async fn connection() -> (Status, Json<ConnectionResult>) {
// Get session cookie
let _cookie = match get_cookie().await {
Ok(cookie) => cookie,
Err(reason) => return (Status::InternalServerError, Json(new_error(reason))),
};
(Status::Ok, Json(ConnectionResult::Ok()))
}
async fn get_cookie<'a>() -> Result<&'a String, String> {
match SESSION_COOKIE.get() {
Some(cookie) => Ok(cookie),
None => {
// Try to create cookie
let _ = create_cookie().await?;
// Try to get cookie again
match SESSION_COOKIE.get() {
Some(cookie) => Ok(cookie),
None => Err("Error getting session cookie".into()),
}
}
}
}
/// Tries to connect to the online classroom, and get a session cookie.
/// Stores the session coookie in a global static variable.
pub async fn create_cookie() -> Result<(), String> {
let clasroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!");
let clasroom_user =
std::env::var("CLASSROOM_USER").expect("CLASSROOM_USER env var is not set!");
let clasroom_password =
std::env::var("CLASSROOM_PASSWORD").expect("CLASSROOM_PASSWORD env var is not set!");
let params = [
("login", clasroom_user),
("password", clasroom_password),
("submitAuth", "".into()),
("_qf__formLogin", "".into()),
];
let client = Client::new();
let result = client
.post(format!("{}/index.php", clasroom_url))
.form(&params)
.send()
.await;
match result {
Ok(response) => {
let Some(session_cookie) = response.cookies().find(|c| c.name() == "ch_sid") else {
return Err("Response succeeded, but no session cookie was foun".into());
};
match SESSION_COOKIE.set(session_cookie.value().into()) {
Ok(_) => Ok(()),
Err(error) => Err(format!("Error setting session cookie: {:?}", error)),
}
}
Err(error) => Err(format!("Error connecting to online classroom: {:?}", error)),
}
}

View File

@ -0,0 +1,58 @@
import { Match, Switch, createSignal, onMount } from "solid-js";
type ConnectionStatus = "connected" | "connecting" | "disconnected" | "error";
export function ClassroomConection() {
const [status, setStatus] = createSignal<ConnectionStatus>("disconnected");
const connectToRemote = () => {
setStatus("connecting");
fetch(`${import.meta.env.VITE_BACKEND_URL}/api/classroom/connect`)
.then((response) => {
if (response.ok) {
setStatus("connected");
} else {
response.json().then((json) => {
console.error(json);
setStatus("error");
});
}
})
.catch((err) => {
console.error(err);
setStatus("error");
});
// setTimeout(() => setStatus("disconnected"), 5000);
};
onMount(connectToRemote);
return (
<div class="bg-c-surface-variant text-c-on-surface-variant rounded-md p-2 mt-4">
Conexión al aula virtual:&nbsp;
<Switch fallback={"Desconectado"}>
<Match when={status() === "connected"}>
<span class="bg-c-success text-c-on-success px-2 rounded select-none font-mono">
Conectado
</span>
</Match>
<Match when={status() === "connecting"}>
<span class="font-mono" style={{color: "orange"}}>
Conectando...
</span>
</Match>
<Match when={status() === "error"}>
<span class="bg-c-error text-c-on-error px-2 rounded font-mono">
Error
</span>
</Match>
<Match when={status() === "disconnected"}>
<span class="bg-c-error-container text-c-on-error-container px-2 rounded font-mono">
Desconectado
</span>
</Match>
</Switch>
</div>
);
}

View File

@ -1,6 +1,7 @@
import { Show, createSignal } from "solid-js"; import { Show, createSignal } from "solid-js";
import { Search } from "../certs/Search"; import { Search } from "../certs/Search";
import { Person } from "../types/Person"; import { Person } from "../types/Person";
import { ClassroomConection } from "./ConnectionStatus";
export function OnlineClassroom() { export function OnlineClassroom() {
const [person, setPerson] = createSignal<Person | null>(null); const [person, setPerson] = createSignal<Person | null>(null);
@ -18,13 +19,7 @@ export function OnlineClassroom() {
); );
} }
function ClassroomConection() {
return (
<div>
Connection status
</div>
);
}
function ClassroomUsers(props: {person: Person}) { function ClassroomUsers(props: {person: Person}) {
return ( return (

View File

@ -17,6 +17,9 @@
--c-green-outline: #8d9387; --c-green-outline: #8d9387;
--c-green-surface-variant: #43483f; --c-green-surface-variant: #43483f;
--c-green-on-surface-variant: #c3c8bc; --c-green-on-surface-variant: #c3c8bc;
--c-green-success: #adc6ff;
--c-green-on-success: #002e69;
} }
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
:root { :root {