Skip to content

Commit

Permalink
non opaque error
Browse files Browse the repository at this point in the history
  • Loading branch information
kariy committed Jun 14, 2024
1 parent 01fd545 commit 9396dd0
Showing 1 changed file with 27 additions and 10 deletions.
37 changes: 27 additions & 10 deletions src/session.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
use std::io;
use std::{fs, path::PathBuf};

use anyhow::Context;
use axum::{extract::State, routing::post, Json, Router};
use serde::{Deserialize, Serialize};
use starknet::core::types::FieldElement;
use thiserror::Error;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tower_http::cors::CorsLayer;
use tracing::trace;
use url::Url;

use crate::credential::{Credentials, SLOT_DIR};
use crate::credential::{self, Credentials, SLOT_DIR};
use crate::{browser, server::LocalServer};

const SESSION_CREATION_PAGE: &str = "https://x.cartridge.gg/slot/session";
const SESSION_FILE_BASE_NAME: &str = "session.json";

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -40,14 +43,29 @@ pub struct SessionCredentials {
pub authorization: Vec<FieldElement>,
}

#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
IO(#[from] io::Error),

#[error(transparent)]
Auth(#[from] credential::Error),

#[error(transparent)]
Serde(#[from] serde_json::Error),

#[error(transparent)]
Other(#[from] anyhow::Error),
}

/// Retrieves the session for the given chain id of the currently authenticated user.
/// Returns `None` if no session can be found for the chain id.
///
/// # Errors
///
/// This function will return an error if there is no authenticated user.
///
pub fn get(chain_id: FieldElement) -> anyhow::Result<Option<SessionDetails>> {
pub fn get(chain_id: FieldElement) -> Result<Option<SessionDetails>, Error> {
let credentials = Credentials::load()?;
let username = credentials.account.expect("id must exist").id;
let path = get_file_path(&username, chain_id);
Expand All @@ -66,7 +84,7 @@ pub fn get(chain_id: FieldElement) -> anyhow::Result<Option<SessionDetails>> {
///
/// This function will return an error if there is no authenticated user.
///
pub fn store(chain_id: FieldElement, session: &SessionDetails) -> anyhow::Result<PathBuf> {
pub fn store(chain_id: FieldElement, session: &SessionDetails) -> Result<PathBuf, Error> {
// TODO: maybe can store the authenticated user in a global variable so that
// we don't have to call load again if we already did it before.
let credentials = Credentials::load()?;
Expand Down Expand Up @@ -94,7 +112,7 @@ pub fn store(chain_id: FieldElement, session: &SessionDetails) -> anyhow::Result
/// This function will return an error if there is no authenticated user.
///
#[tracing::instrument(level = "trace", skip(rpc_url), fields(policies = policies.len()))]
pub async fn create<U>(rpc_url: U, policies: &[Policy]) -> anyhow::Result<SessionDetails>
pub async fn create<U>(rpc_url: U, policies: &[Policy]) -> Result<SessionDetails, Error>
where
U: Into<Url>,
{
Expand All @@ -104,7 +122,7 @@ where
let rpc_url: Url = rpc_url.into();
let mut rx = open_session_creation_page(&username, rpc_url.as_str(), policies)?;

rx.recv().await.context("Channel dropped.")
Ok(rx.recv().await.context("Channel dropped.")?)
}

/// Starts the session creation process by opening the browser to the Cartridge keychain to prompt
Expand All @@ -115,7 +133,7 @@ fn open_session_creation_page(
policies: &[Policy],
) -> anyhow::Result<Receiver<SessionDetails>> {
let params = prepare_query_params(username, rpc_url, policies)?;
let url = format!("https://x.cartridge.gg/slot/session?{params}");
let url = format!("{SESSION_CREATION_PAGE}?{params}");

let (tx, rx) = channel::<SessionDetails>(1);
let server = callback_server(tx)?;
Expand Down Expand Up @@ -154,10 +172,9 @@ fn prepare_query_params(

/// Create the callback server that will receive the session token from the browser.
fn callback_server(tx: Sender<SessionDetails>) -> anyhow::Result<LocalServer> {
let handler = move |State(tx): State<Sender<SessionDetails>>,
Json(session): Json<SessionDetails>| async move {
let handler = move |tx: State<Sender<SessionDetails>>, session: Json<SessionDetails>| async move {
trace!("Received session token from the browser.");
tx.send(session).await.expect("qed; channel closed");
tx.0.send(session.0).await.expect("qed; channel closed");
};

let router = Router::new()
Expand All @@ -178,7 +195,7 @@ fn get_file_path(username: &str, chain_id: FieldElement) -> PathBuf {
#[cfg(test)]
mod tests {
#[test]
fn get_session() {}
fn get_session_when_not_authenticated() {}

#[test]
fn store_session() {}
Expand Down

0 comments on commit 9396dd0

Please sign in to comment.