-
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathauth_api.rs
More file actions
111 lines (98 loc) · 3.53 KB
/
auth_api.rs
File metadata and controls
111 lines (98 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#[cfg(not(any(feature = "extras-session", feature = "session")))]
fn main() {
eprintln!(
"Run this example with session support enabled:\n cargo run -p rustapi-rs --example auth_api --features extras-session"
);
}
#[cfg(any(feature = "extras-session", feature = "session"))]
use rustapi_rs::extras::session::{MemorySessionStore, Session, SessionConfig, SessionLayer};
#[cfg(any(feature = "extras-session", feature = "session"))]
use rustapi_rs::prelude::*;
#[cfg(any(feature = "extras-session", feature = "session"))]
use std::time::Duration;
#[cfg(any(feature = "extras-session", feature = "session"))]
#[derive(Debug, Deserialize, Schema)]
struct LoginRequest {
user_id: String,
}
#[cfg(any(feature = "extras-session", feature = "session"))]
#[derive(Debug, Serialize, Schema)]
struct SessionView {
authenticated: bool,
user_id: Option<String>,
refreshed: bool,
session_id: Option<String>,
}
#[cfg(any(feature = "extras-session", feature = "session"))]
async fn session_view(session: &Session) -> SessionView {
let user_id = session.get::<String>("user_id").await.ok().flatten();
let refreshed = session
.get::<bool>("refreshed")
.await
.ok()
.flatten()
.unwrap_or(false);
let session_id = session.id().await;
SessionView {
authenticated: user_id.is_some(),
user_id,
refreshed,
session_id,
}
}
#[cfg(any(feature = "extras-session", feature = "session"))]
async fn login(session: Session, Json(payload): Json<LoginRequest>) -> Json<SessionView> {
session.cycle_id().await;
session
.insert("user_id", &payload.user_id)
.await
.expect("serializing user_id into the session should succeed");
session
.insert("refreshed", false)
.await
.expect("serializing refreshed flag into the session should succeed");
Json(session_view(&session).await)
}
#[cfg(any(feature = "extras-session", feature = "session"))]
async fn me(session: Session) -> Json<SessionView> {
Json(session_view(&session).await)
}
#[cfg(any(feature = "extras-session", feature = "session"))]
async fn refresh(session: Session) -> Json<SessionView> {
if session.contains("user_id").await {
session.cycle_id().await;
session
.insert("refreshed", true)
.await
.expect("serializing refreshed flag into the session should succeed");
}
Json(session_view(&session).await)
}
#[cfg(any(feature = "extras-session", feature = "session"))]
async fn logout(session: Session) -> NoContent {
session.destroy().await;
NoContent
}
#[cfg(any(feature = "extras-session", feature = "session"))]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Starting session auth example...");
println!(" -> POST http://127.0.0.1:3000/auth/login {{\"user_id\":\"demo-user\"}}");
println!(" -> GET http://127.0.0.1:3000/auth/me");
println!(" -> POST http://127.0.0.1:3000/auth/refresh");
println!(" -> POST http://127.0.0.1:3000/auth/logout");
RustApi::new()
.layer(SessionLayer::new(
MemorySessionStore::new(),
SessionConfig::new()
.cookie_name("rustapi_auth")
.secure(false)
.ttl(Duration::from_secs(60 * 30)),
))
.route("/auth/login", post(login))
.route("/auth/me", get(me))
.route("/auth/refresh", post(refresh))
.route("/auth/logout", post(logout))
.run("127.0.0.1:3000")
.await
}