1use actix_session;
13use actix_web::{cookie::time::format_description::modifier::End, HttpRequest, HttpResponse, Responder};
14use argon2::password_hash::rand_core::impls;
15use sqlx::{self, Postgres};
16
17use crate::auth;
18
19pub enum GenerateSessionReturn {
20 SessionGeneratedAndSaved(),
21 FailedToGenerate(String),
22 ClientSessionNotSetCorrectly(),
23}
24
25pub enum ValidatedSessionReturn<'a> {
26 ValidSession(),
27 SessionOutOfDate(),
28 SessionInvalid(),
30 ClientSessionNotSetCorrectly(&'a str),
31}
32
33pub enum EndSessionsReturn<'a> {
34 RemovedSessions(),
35 SessionInvalid(),
36 ClientSessionNotSetCorrectly(&'a str),
37 DatabaseError(String),
38}
39
40pub async fn generate_session(
44 session: actix_session::Session,
45 creds: auth::Credentials,
46 pool: &sqlx::Pool<Postgres>,
47) -> GenerateSessionReturn {
48 let local_session = match auth::generate_session(&creds, pool, auth::SESSION_VALID_FOR_SECONDS).await {
49 Ok(session) => session,
50 Err(err) => {
51 return GenerateSessionReturn::FailedToGenerate(format!("Failed with {:?}", err))
52 }
53 };
54
55 let _user_name_insert = match session.insert("user_name", &local_session.user_name) {
56 Ok(_) => (),
57 Err(_) => return GenerateSessionReturn::ClientSessionNotSetCorrectly(),
58 };
59
60 let _session_token_insert = match session.insert("session_token", &local_session.session_token)
61 {
62 Ok(_) => (),
63 Err(_) => return GenerateSessionReturn::ClientSessionNotSetCorrectly(),
64 };
65
66 let _time_to_die_insert =
67 match session.insert("time_to_die", &local_session.time_to_die.to_rfc3339()) {
68 Ok(time_to_die) => time_to_die,
69 Err(_) => return GenerateSessionReturn::ClientSessionNotSetCorrectly(),
70 };
71
72 return GenerateSessionReturn::SessionGeneratedAndSaved();
73}
74
75pub async fn generate_session_web_resp(
78 client_session: actix_session::Session,
79 json_creds: actix_web::web::Json<auth::Credentials>,
80 pool: actix_web::web::Data<sqlx::Pool<Postgres>>,
81) -> impl Responder {
82 let creds = auth::Credentials {
83 password: json_creds.password.to_string(),
84 user_name: json_creds.user_name.to_string(),
85 realm: json_creds.realm.to_string(),
86 };
87
88 match generate_session(client_session, creds, &pool).await {
89 GenerateSessionReturn::ClientSessionNotSetCorrectly() => {
90 actix_web::HttpResponse::InternalServerError().body("Session failed to be set")
91 }
92 GenerateSessionReturn::FailedToGenerate(err) => {
93 actix_web::HttpResponse::InternalServerError()
94 .body(format!("Session failed to generate: {:?}", err))
95 }
96 GenerateSessionReturn::SessionGeneratedAndSaved() => {
97 actix_web::HttpResponse::Accepted().body("Session Good")
98 }
99 }
100}
101
102pub async fn validate_session(
106 client_session: actix_session::Session,
107 pool: &sqlx::Pool<Postgres>,
108) -> ValidatedSessionReturn {
109 let user_name = match client_session.get::<String>("user_name") {
110 Ok(user_name_option) => match user_name_option {
111 Some(user_name) => user_name,
112 None => return ValidatedSessionReturn::ClientSessionNotSetCorrectly("user_name"),
113 },
114 Err(_) => return ValidatedSessionReturn::ClientSessionNotSetCorrectly("user_name"),
115 };
116
117 let session_token = match client_session.get::<String>("session_token") {
118 Ok(session_token_option) => match session_token_option {
119 Some(session_token) => session_token,
120 None => return ValidatedSessionReturn::ClientSessionNotSetCorrectly("session_token"),
121 },
122 Err(_) => return ValidatedSessionReturn::ClientSessionNotSetCorrectly("session_token"),
123 };
124
125 let time_to_die = match client_session.get::<String>("time_to_die") {
126 Ok(session_token_option) => match session_token_option {
127 Some(session_token) => session_token,
128 None => return ValidatedSessionReturn::ClientSessionNotSetCorrectly("time_to_die"),
129 },
130 Err(_) => return ValidatedSessionReturn::ClientSessionNotSetCorrectly("time_to_die"),
131 };
132
133 let time = match chrono::DateTime::parse_from_rfc3339(&time_to_die) {
134 Ok(time) => time,
135 Err(_) => return ValidatedSessionReturn::ClientSessionNotSetCorrectly("time set wrong in time_to_die"),
136 };
137
138 let local_session = auth::Session {
139 user_name: user_name,
140 session_token: session_token,
141 time_to_die: time.into(),
142 };
143
144 match auth::validate_session(&local_session, &pool).await {
145 auth::SessionValidated::ValidSession() => ValidatedSessionReturn::ValidSession(),
146 auth::SessionValidated::InvalidSession() => {
147 return ValidatedSessionReturn::SessionInvalid()
148 }
149 }
150}
151
152pub async fn validate_session_web_resp(
155 client_session: actix_session::Session,
156 pool: actix_web::web::Data<sqlx::Pool<Postgres>>,
157) -> impl Responder {
158 match validate_session(client_session, &pool).await {
159 ValidatedSessionReturn::ClientSessionNotSetCorrectly(err) => {
160 HttpResponse::InternalServerError().body(format!("Client Session not set correctly\nGot err: {:?}", err))
161 }
162 ValidatedSessionReturn::SessionInvalid() => {
163 HttpResponse::InternalServerError().body("Session invalid")
164 }
165 ValidatedSessionReturn::SessionOutOfDate() => {
166 HttpResponse::InternalServerError().body("Session out of date")
167 }
168 ValidatedSessionReturn::ValidSession() => HttpResponse::Accepted().body("Session Good"),
169 }
170}
171
172pub async fn end_sessions<'a> (
173 client_session: actix_session::Session,
174 pool: actix_web::web::Data<sqlx::Pool<Postgres>>,
175) -> EndSessionsReturn<'a> {
176 let user_name = match client_session.get::<String>("user_name") {
177 Ok(user_name_option) => match user_name_option {
178 Some(user_name) => user_name,
179 None => return EndSessionsReturn::ClientSessionNotSetCorrectly("user_name"),
180 },
181 Err(_) => return EndSessionsReturn::ClientSessionNotSetCorrectly("user_name"),
182 };
183
184 let session_token = match client_session.get::<String>("session_token") {
185 Ok(session_token_option) => match session_token_option {
186 Some(session_token) => session_token,
187 None => return EndSessionsReturn::ClientSessionNotSetCorrectly("session_token"),
188 },
189 Err(_) => return EndSessionsReturn::ClientSessionNotSetCorrectly("session_token"),
190 };
191
192 let time_to_die = match client_session.get::<String>("time_to_die") {
193 Ok(session_token_option) => match session_token_option {
194 Some(session_token) => session_token,
195 None => return EndSessionsReturn::ClientSessionNotSetCorrectly("time_to_die"),
196 },
197 Err(_) => return EndSessionsReturn::ClientSessionNotSetCorrectly("time_to_die"),
198 };
199
200 let time = match chrono::DateTime::parse_from_rfc3339(&time_to_die) {
201 Ok(time) => time,
202 Err(_) => return EndSessionsReturn::ClientSessionNotSetCorrectly("time set wrong in time_to_die"),
203 };
204
205 let local_session = auth::Session {
206 user_name: user_name,
207 session_token: session_token,
208 time_to_die: time.into(),
209 };
210
211 match auth::end_sessions(&local_session, &pool).await {
212 auth::EndSessionReturn::BadSession() => EndSessionsReturn::SessionInvalid(),
213 auth::EndSessionReturn::DataBaseError(err) => EndSessionsReturn::DatabaseError(err.to_string()),
214 auth::EndSessionReturn::Ended() => EndSessionsReturn::RemovedSessions(),
215
216 }
217}
218
219pub async fn end_sessions_web_resp(
220 client_session: actix_session::Session,
221 pool: actix_web::web::Data<sqlx::Pool<Postgres>>,
222) -> impl Responder {
223 match end_sessions(client_session, pool).await {
224 EndSessionsReturn::RemovedSessions() => HttpResponse::Accepted().body("Removed All Sessions"),
225 EndSessionsReturn::ClientSessionNotSetCorrectly(msg) => HttpResponse::BadRequest().body(msg),
226 EndSessionsReturn::SessionInvalid() => HttpResponse::Forbidden().body("Invalid Session"),
227 EndSessionsReturn::DatabaseError(msg) => HttpResponse::InternalServerError().body(format!("Database Issue: {msg}"))
228 }
229}