|
| 1 | +use rwf::controller::oidc::*; |
| 2 | +use rwf::model::{get_connection, migrate}; |
| 3 | +use rwf::prelude::*; |
| 4 | +#[derive(macros::Model, Clone, Serialize, Deserialize)] |
| 5 | +struct User { |
| 6 | + id: Option<i64>, |
| 7 | + name: String, |
| 8 | + email: String, |
| 9 | + token: serde_json::Value, |
| 10 | + expire: OffsetDateTime, |
| 11 | +} |
| 12 | +#[async_trait] |
| 13 | +impl OidcUser for User { |
| 14 | + async fn from_token( |
| 15 | + token: StandardTokenResponse<CoreIdTokenFields, CoreTokenType>, |
| 16 | + userinfo: UserInfoClaims<EmptyAdditionalClaims, CoreGenderClaim>, |
| 17 | + ) -> Result<Self, rwf::model::Error> { |
| 18 | + let name = userinfo |
| 19 | + .standard_claims() |
| 20 | + .preferred_username() |
| 21 | + .unwrap() |
| 22 | + .to_string(); |
| 23 | + let email = userinfo.standard_claims().email().unwrap().to_string(); |
| 24 | + let expire = OffsetDateTime::now_utc() |
| 25 | + .checked_add(Duration::nanoseconds( |
| 26 | + token.expires_in().unwrap().as_nanos() as i64, |
| 27 | + )) |
| 28 | + .unwrap(); |
| 29 | + let token = serde_json::json!({"access": token.access_token(), "refresh": token.refresh_token().unwrap()}); |
| 30 | + let mut conn = get_connection().await?; |
| 31 | + User::create(&[ |
| 32 | + ("name", name.to_value()), |
| 33 | + ("email", email.to_value()), |
| 34 | + ("expire", expire.to_value()), |
| 35 | + ("token", token.to_value()), |
| 36 | + ]) |
| 37 | + .unique_by(&["email"]) |
| 38 | + .fetch(&mut conn) |
| 39 | + .await |
| 40 | + } |
| 41 | + |
| 42 | + fn access_token(&self) -> AccessToken { |
| 43 | + serde_json::from_value(self.token.get("access").unwrap().clone()).unwrap() |
| 44 | + } |
| 45 | + |
| 46 | + fn refresh_token(&self) -> RefreshToken { |
| 47 | + serde_json::from_value(self.token.get("refresh").unwrap().clone()).unwrap() |
| 48 | + } |
| 49 | + |
| 50 | + fn expire(&self) -> &OffsetDateTime { |
| 51 | + &self.expire |
| 52 | + } |
| 53 | + |
| 54 | + fn update_token( |
| 55 | + mut self, |
| 56 | + token: StandardTokenResponse<CoreIdTokenFields, CoreTokenType>, |
| 57 | + ) -> Self { |
| 58 | + self.token = serde_json::json!({"access": token.access_token(), "refresh": token.refresh_token().unwrap()}); |
| 59 | + self |
| 60 | + } |
| 61 | +} |
| 62 | + |
| 63 | +struct TestController { |
| 64 | + auth: AuthHandler, |
| 65 | +} |
| 66 | + |
| 67 | +impl Default for TestController { |
| 68 | + fn default() -> Self { |
| 69 | + Self { |
| 70 | + auth: OidcAuthentication::<User>::default().handler(), |
| 71 | + } |
| 72 | + } |
| 73 | +} |
| 74 | + |
| 75 | +#[async_trait] |
| 76 | +impl Controller for TestController { |
| 77 | + fn auth(&self) -> &AuthHandler { |
| 78 | + &self.auth |
| 79 | + } |
| 80 | + |
| 81 | + async fn handle(&self, request: &Request) -> Result<Response, Error> { |
| 82 | + let mut conn = get_connection().await?; |
| 83 | + let user: User = request.user_required(&mut conn).await?; |
| 84 | + Ok(Response::new().html(format!("<h1>Hello {}</h1>", user.name))) |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +#[tokio::main] |
| 89 | +async fn main() -> Result<(), rwf::http::Error> { |
| 90 | + migrate().await?; |
| 91 | + rwf::http::Server::new(vec![ |
| 92 | + route!("/" => TestController), |
| 93 | + // Take OIDC Config from rwf.toml (or Env). |
| 94 | + route!("/oidc" => OidcController::<User>), |
| 95 | + ]) |
| 96 | + .launch() |
| 97 | + .await |
| 98 | +} |
0 commit comments