Skip to content

Commit

Permalink
feat(rust): wip add "lease get" service
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianbenavides committed Sep 12, 2024
1 parent 5ef3ee4 commit 8b5013f
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ impl InfluxDBTokenLessorWorkerTrait for InfluxDBTokenLessorWorker {
_ctx: &Context,
requester: &Identifier,
) -> Result<Response<LeaseToken>, Response<ockam_core::api::Error>> {
debug!("Creating token");
debug!(%requester, "Creating token");
let (
http_client,
influxdb_address,
Expand All @@ -229,7 +229,7 @@ impl InfluxDBTokenLessorWorkerTrait for InfluxDBTokenLessorWorker {
};

let expires = OffsetDateTime::now_utc() + token_ttl;
let description = InfluxDBCreateTokenResponse::pack_metadata(requester, expires);
let description = InfluxDBTokenResponse::pack_metadata(requester, expires);

let req = http_client
.post(format!("{}/api/v2/authorizations", influxdb_address))
Expand All @@ -241,22 +241,16 @@ impl InfluxDBTokenLessorWorkerTrait for InfluxDBTokenLessorWorker {
));
match req.send().await {
Ok(res) => {
let influxdb_token =
res.json::<InfluxDBCreateTokenResponse>()
.await
.map_err(|e| {
ApiError::core(format!("Failed to parse InfluxDB token from json: {e}"))
})?;
let influxdb_token = res.json::<InfluxDBTokenResponse>().await.map_err(|e| {
ApiError::core(format!("Failed to parse InfluxDB token from json: {e}"))
})?;
let lease_token: Option<LeaseToken> = influxdb_token.try_into().map_err(|e| {
ApiError::core(format!(
"Failed to parse InfluxDB token as a LeaseToken: {e}"
))
})?;
match lease_token {
Some(lease_token) => {
info!("Generated token!!: {:?}", lease_token);
Ok(Response::ok().body(lease_token))
}
Some(lease_token) => Ok(Response::ok().body(lease_token)),
None => {
warn!("Token does not contain Ockam metadata, ignoring");
Err(Response::bad_request_no_request(
Expand All @@ -276,15 +270,59 @@ impl InfluxDBTokenLessorWorkerTrait for InfluxDBTokenLessorWorker {

async fn get_token(
&self,
ctx: &Context,
_ctx: &Context,
requester: &Identifier,
token_id: &str,
) -> Result<Response<LeaseToken>, Response<ockam_core::api::Error>> {
// TODO https://docs.influxdata.com/influxdb/v2/api/#operation/GetAuthorizationsID
// NOTE!!!: check if the identifier that created it is the same
// one requesting it. Otherwise the user is not authorized for doing it.
debug!("Getting token");
todo!()
debug!(%requester, %token_id, "Getting token");
let (http_client, influxdb_address, influxdb_token) = {
let state = self.state.read().await;
(
state.http_client.clone(),
state.influxdb_address.clone(),
state.influxdb_token.clone(),
)
};
let req = http_client
.get(format!("{}/api/v2/authorizations", influxdb_address))
.header("Authorization", format!("Token {}", influxdb_token))
.header("Content-Type", "application/json");

match req.send().await {
Ok(res) => {
let influxdb_token = res.json::<InfluxDBTokenResponse>().await.map_err(|e| {
ApiError::core(format!("Failed to parse InfluxDB token from json: {e}"))
})?;
debug!(%requester, %token_id, "Received token: {:?}", influxdb_token);
let lease_token: Option<LeaseToken> = influxdb_token.try_into().map_err(|e| {
ApiError::core(format!(
"Failed to parse InfluxDB token as a LeaseToken: {e}"
))
})?;
match lease_token {
Some(lease_token) => {
if requester.eq(&lease_token.issued_for) {
Ok(Response::ok().body(lease_token))
} else {
warn!(%requester, %token_id, "Token not authorized");
Err(Response::unauthorized_no_request(
"Token not authorized for requester",
))
}
}
None => {
warn!(%requester, %token_id, "Token not found");
Err(Response::not_found_no_request(
"Token does not contain Ockam metadata",
))
}
}
}
Err(e) => {
error!("Failed to list tokens: {e:?}");
Err(Response::internal_error_no_request("Failed to list tokens"))
}
}
}

async fn revoke_token(
Expand All @@ -296,7 +334,7 @@ impl InfluxDBTokenLessorWorkerTrait for InfluxDBTokenLessorWorker {
// TODO: https://docs.influxdata.com/influxdb/v2/api/#operation/DeleteAuthorizationsID
// NOTE!!!: first retrieve the token, check if the identifier that created it is the same
// one deleting it, and if so revoke it. Otherwise the user is not authorized for doing it.
debug!("Revoking token");
debug!(%requester, %token_id, "Revoking token");
Ok(Response::ok())
}

Expand All @@ -305,7 +343,7 @@ impl InfluxDBTokenLessorWorkerTrait for InfluxDBTokenLessorWorker {
_ctx: &Context,
requester: &Identifier,
) -> Result<Response<Vec<LeaseToken>>, Response<ockam_core::api::Error>> {
debug!("Listing tokens");
debug!(%requester, "Listing tokens");
let (http_client, influxdb_address, influxdb_token) = {
let state = self.state.read().await;
(
Expand Down Expand Up @@ -359,7 +397,7 @@ impl InfluxDBTokenLessorWorkerTrait for InfluxDBTokenLessorWorker {

/// Token returned by InfluxDB API
#[derive(serde::Deserialize, Debug, PartialEq, Eq)]
pub struct InfluxDBCreateTokenResponse {
pub struct InfluxDBTokenResponse {
pub id: String,
pub description: String,
pub token: String,
Expand All @@ -370,10 +408,10 @@ pub struct InfluxDBCreateTokenResponse {

/// Return a `LeaseToken` if it's an Ockam token (i.e., if the `description` contains a valid Ockam metadata).
/// If the metadata is not found, the token will be ignored.
impl TryFrom<InfluxDBCreateTokenResponse> for Option<LeaseToken> {
impl TryFrom<InfluxDBTokenResponse> for Option<LeaseToken> {
type Error = ockam_core::Error;

fn try_from(token: InfluxDBCreateTokenResponse) -> Result<Self, Self::Error> {
fn try_from(token: InfluxDBTokenResponse) -> Result<Self, Self::Error> {
match token.unpack_metadata()? {
Some((issued_for, expires)) => Ok(Some(LeaseToken {
id: token.id,
Expand All @@ -395,7 +433,7 @@ impl TryFrom<InfluxDBCreateTokenResponse> for Option<LeaseToken> {
}
}

impl InfluxDBCreateTokenResponse {
impl InfluxDBTokenResponse {
/// The InfluxDB tokens only have a description field that can be used to store metadata.
/// The Ockam `LeaseToken` will pack in the description field the identifier that created the token,
/// and its expiration time.
Expand Down Expand Up @@ -424,7 +462,7 @@ impl InfluxDBCreateTokenResponse {
#[derive(serde::Deserialize, Debug, PartialEq, Eq)]
struct InfluxDBListTokensResponse {
#[serde(rename = "authorizations")]
tokens: Vec<InfluxDBCreateTokenResponse>,
tokens: Vec<InfluxDBTokenResponse>,
#[serde(rename = "links")]
pagination: InfluxDBPagination,
}
Expand All @@ -446,7 +484,7 @@ mod tests {
let expires_at_timestamp = expires_at.unix_timestamp();
let created_at = "2024-09-12T16:23:54Z";
let created_at_timestamp = 1726158234;
let token = InfluxDBCreateTokenResponse {
let token = InfluxDBTokenResponse {
id: "token_id".to_string(),
description: format!("OCKAM:{identifier}:{expires_at_timestamp}"),
token: "token".to_string(),
Expand Down
5 changes: 5 additions & 0 deletions implementations/rust/ockam/ockam_core/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,11 @@ impl Response {
Response::builder(re, Status::Unauthorized)
}

pub fn unauthorized_no_request(msg: &str) -> Response<Error> {
let e = Error::new_without_path().with_message(msg);
Response::builder(Id::default(), Status::Unauthorized).body(e)
}

pub fn forbidden_no_request(re: Id) -> Response {
Response::builder(re, Status::Forbidden)
}
Expand Down

0 comments on commit 8b5013f

Please sign in to comment.