Skip to content

Commit

Permalink
Manual Upsert and Migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
lucemans committed Jul 27, 2024
1 parent 2fc4b5d commit f1a9ca6
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 28 deletions.
21 changes: 21 additions & 0 deletions engine/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dotenv = "0.15.0"
dotenvy = "0.15.7"
openid = "0.14.0"
poem = "3.0.4"
poem-openapi = { version = "5.0.3", features = ["email", "email_address", "swagger-ui"] }
poem-openapi = { version = "5.0.3", features = ["email", "email_address", "redoc", "static-files"] }
reqwest = "0.12.5"
serde = "1.0.204"
serde_json = "1.0.120"
Expand Down
2 changes: 1 addition & 1 deletion engine/migrations/0001_init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ CREATE TABLE IF NOT EXISTS users
id SERIAL PRIMARY KEY,
oauth_sub VARCHAR(255) NOT NULL,
oauth_data JSONB NOT NULL,
nickname VARCHAR(255) NOT NULL
nickname VARCHAR(255)
);
62 changes: 47 additions & 15 deletions engine/src/database/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use std::{ops::Deref, str::FromStr};

use async_std::stream::StreamExt;
use openid::Userinfo;
use serde_json::Value;
use sqlx::{
postgres::PgPoolOptions,
query::{self, Query},
types::Json,
Execute, Executor, PgPool,
};
use tracing::info;
Expand Down Expand Up @@ -32,21 +36,49 @@ impl Database {
Ok(())
}

pub async fn upsert_get_user(&self, oauth_userinfo: &Userinfo) -> Result<UserData, sqlx::Error> {
// Check if the user exists, return its info, otherwise create a new user, and return its info.

let sub = oauth_userinfo.sub.as_ref().unwrap().to_string();

let mut userdata =
sqlx::query_as::<_, UserData>("SELECT * FROM users WHERE oauth_sub = ? LIMIT 1")
.bind(sub)
.fetch(&self.pool);

let x = userdata.next().await.unwrap().unwrap();

info!("upsert_get_user: {:?}", x);

Ok(x)
/// Check if the user exists, return its info, otherwise create a new user, and return its info.
pub async fn upsert_get_user(
&self,
oauth_userinfo: &Userinfo,
) -> Result<UserData, sqlx::Error> {
let sub = oauth_userinfo.sub.as_deref().unwrap();

info!("upsert_get_user: sub: {}", sub);

match sqlx::query_as::<_, UserData>("SELECT * FROM users WHERE oauth_sub = $1")
.bind(sub)
.fetch_one(&self.pool)
.await
{
Ok(x) => {
info!("upsert_get_user_found: {:?}", x);
Ok(x)
}
Err(e) => {
info!("upsert_get_user: not found {}", e);

let mut local_userdata = UserData {
id: 0,
oauth_sub: sub.to_string(),
oauth_data: Json(oauth_userinfo.clone()),
nickname: None,
};

let insert_query = sqlx::query!(
"INSERT INTO users (oauth_sub, oauth_data) VALUES ($1, $2) RETURNING id",
local_userdata.oauth_sub,
Json(&oauth_userinfo) as _
)
.fetch_one(&self.pool)
.await?;

info!("upsert_get_user: {:?}", insert_query);

local_userdata.id = insert_query.id;

Ok(local_userdata)
}
}
}

// pub async fn insert_user(&self, user: &Userinfo) -> Result<u64, sqlx::Error> {
Expand Down
6 changes: 4 additions & 2 deletions engine/src/models/user_data.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use openid::Userinfo;
use serde::{Deserialize, Serialize};
use sqlx::types::Json;


#[derive(sqlx::FromRow, Debug, Clone, Serialize, Deserialize)]
pub struct UserData {
pub id: i64,
pub id: i32,
pub oauth_sub: String,
pub oauth_data: Option<String>,
pub oauth_data: Json<Userinfo>,
pub nickname: Option<String>,
}
14 changes: 8 additions & 6 deletions engine/src/routes/auth.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::state::AppState;
use openid::{Options, Token};
use poem::{web::{Data, Query, Redirect}, IntoResponse};
use poem::{handler, web::{headers::Header, Data, Query, Redirect}, IntoResponse};
use serde::Deserialize;
use std::sync::Arc;

pub async fn login(state: Data<Arc<AppState>>) -> impl IntoResponse {
#[handler]
pub async fn login(state: Data<&Arc<AppState>>) -> impl IntoResponse {
// let discovery_url = "http://localhost:8080/realms/master/.well-known/openid-configuration";

// let http_client = reqwest::Client::new();
Expand Down Expand Up @@ -40,7 +41,8 @@ pub struct MyQuery {
pub prompt: Option<String>,
}

pub async fn callback(query: Query<MyQuery>, state: Data<Arc<AppState>>) -> impl IntoResponse {
#[handler]
pub async fn callback(query: Query<MyQuery>, state: Data<&Arc<AppState>>) -> impl IntoResponse {
let mut token = state.openid.request_token(&query.code).await.unwrap();

let mut token = Token::from(token);
Expand All @@ -61,9 +63,9 @@ pub async fn callback(query: Query<MyQuery>, state: Data<Arc<AppState>>) -> impl
.await
.unwrap();

format!("Hello {:?}", user.nickname);

// TODO: return a token

serde_json::to_string(&user).unwrap()
let token = "hello".to_string();

Redirect::temporary("http://localhost:3000/hello").with_header("Set-Cookie", format!("property.v3x.token={}", token))
}
25 changes: 25 additions & 0 deletions engine/src/routes/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>enstate.rs - Lightweight ENS API</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/docs/favicon.png" />
<meta property="og:image" content="/docs/opengraph.png" />
</head>
<body>
<script
id="api-reference"
data-url="/openapi.json"
></script>
<script>
var configuration = {
theme: "blue",
};

var apiReference = document.getElementById("api-reference");
apiReference.dataset.configuration = JSON.stringify(configuration);
</script>
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
</body>
</html>
19 changes: 16 additions & 3 deletions engine/src/routes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::sync::Arc;

use poem::{get, handler, listener::TcpListener, post, web::Path, EndpointExt, Route, Server};
use poem::{get, handler, listener::TcpListener, post, web::{Html, Path}, Endpoint, EndpointExt, Route, Server};
use poem_openapi::{param::Query, payload::PlainText, OpenApi, OpenApiService};

use crate::state::AppState;
Expand All @@ -11,6 +11,7 @@ struct Api;

#[OpenApi]
impl Api {
/// Testing one two three
#[oai(path = "/hello", method = "get")]
async fn index(&self, name: Query<Option<String>>) -> PlainText<String> {
match name.0 {
Expand All @@ -20,15 +21,27 @@ impl Api {
}
}

// returns the html from the index.html file
#[handler]
async fn ui() -> Html<&'static str> {
Html(include_str!("./index.html"))
}

pub async fn serve(state: AppState) -> Result<(), poem::Error> {
let api_service =
OpenApiService::new(Api, "Hello World", "1.0").server("http://localhost:3000/api");

let ui = api_service.swagger_ui();
let spec = api_service.spec_endpoint();

let state = Arc::new(state);

let app = Route::new().nest("/api", api_service).nest("/", ui).data(state);
let app = Route::new()
.at("/login", get(auth::login))
.at("/callback", get(auth::callback))
.nest("/api", api_service)
.nest("/openapi.json", spec)
.at("/", get(ui))
.data(state);
// .at("/", get(root))
// .route("/login", get(auth::login))
// // OAuth Callback route
Expand Down

0 comments on commit f1a9ca6

Please sign in to comment.