Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/project manager #4

Open
wants to merge 53 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
cb310cc
Update Response & Add Endpoints
arturofigueroabim Jan 9, 2024
b25f89a
Update Check Status Endpoint
arturofigueroabim Jan 11, 2024
55bb18e
Add new endpoints
arturofigueroabim Jan 12, 2024
fc5f407
Update Generate Script function
arturofigueroabim Jan 17, 2024
a9aa66d
Add Enums file
arturofigueroabim Jan 18, 2024
58e59b4
Changed: Rename email to user in token params
djuarezgf Jan 23, 2024
7dfacb9
Changed: push generate script instead of get
djuarezgf Jan 23, 2024
b390b66
Update Env variables
arturofigueroabim Jan 24, 2024
46101cb
Update Schema and Request beam functions
arturofigueroabim Jan 29, 2024
4f8e370
Add new endpoint
arturofigueroabim Jan 30, 2024
7a21e54
Re factor Create Task Beam
arturofigueroabim Jan 30, 2024
4300389
Update Project Status Response
arturofigueroabim Feb 1, 2024
affe8f5
Changed: NOTFOUND to NOT_FOUND and WITHDATA to WITH_DATA
djuarezgf Feb 1, 2024
45245ae
Split Project status request
arturofigueroabim Feb 1, 2024
077626a
Update Check Status requests
arturofigueroabim Feb 2, 2024
de16da4
Changed: Enums NOT_FOUND to NOTFOUND and WITH_DATA to WITHDATA
djuarezgf Feb 2, 2024
6e1ac1f
Bugfix
djuarezgf Feb 2, 2024
431bdde
Bugfix + new TODOs
djuarezgf Feb 2, 2024
cde6f61
Add Add token_name to database
arturofigueroabim Feb 5, 2024
fcc7a98
Check Token Status in Opal
arturofigueroabim Feb 5, 2024
5fdd472
Update Token Status
arturofigueroabim Feb 6, 2024
758e3fb
Update Token Status
arturofigueroabim Feb 7, 2024
9bb0009
Update Delete endpoints
arturofigueroabim Feb 8, 2024
388fba4
Update Delete endpoints
arturofigueroabim Feb 8, 2024
f17a5bd
Update refreshToken endpoint
arturofigueroabim Feb 14, 2024
c85663c
Update Create Task Function
arturofigueroabim Feb 14, 2024
93cb922
Update Create Token Task Function
arturofigueroabim Feb 20, 2024
90c03eb
Update Routes and Create task function
arturofigueroabim Feb 21, 2024
155955e
Update Fetch tables names
arturofigueroabim Feb 22, 2024
8174d9e
Change BKs list
arturofigueroabim Feb 23, 2024
bd3fa66
Update Created At format
arturofigueroabim Feb 28, 2024
494a3c3
Update Generate Script Function
arturofigueroabim Feb 29, 2024
1a4af67
Add Authentication Script endpoint
arturofigueroabim Mar 1, 2024
86d3b37
Update Auth Script endpoint
arturofigueroabim Mar 1, 2024
a132b79
Update Auth Script endpoint
arturofigueroabim Mar 1, 2024
60dd970
Update Auth Script endpoint
arturofigueroabim Mar 1, 2024
105d4bf
Add Token Encryption
arturofigueroabim Mar 4, 2024
cb8914c
Update Script
arturofigueroabim Mar 5, 2024
f576051
Update Enum Response
arturofigueroabim Mar 6, 2024
4d4f94b
Formatting update
arturofigueroabim Mar 6, 2024
d42d1e6
Formatting update
arturofigueroabim Mar 7, 2024
88980d9
chore: Relax depency versions and remove rust-crypto
Threated Mar 22, 2024
e24c2ae
Some refactoring and a bit more logging
Threated Apr 2, 2024
b1b42aa
Add timeout to table fetching
Threated Apr 4, 2024
4fa8522
Update Generate Script request
arturofigueroabim Apr 9, 2024
fc49a49
Update logs info
arturofigueroabim Apr 9, 2024
3cb008b
Verify if token is already created
arturofigueroabim Apr 10, 2024
a2ff690
Update logs
arturofigueroabim Apr 11, 2024
bc2fa63
Update logs
arturofigueroabim Apr 11, 2024
d49042e
chore: bump deps
Threated Oct 2, 2024
61382dd
Handle missing or invalid BK
arturofigueroabim Nov 12, 2024
491bc6f
Add error enum
arturofigueroabim Nov 19, 2024
2fa04fd
Update logs
arturofigueroabim Nov 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
BEAM_URL=http://localhost:8081
BEAM_ID=app1.proxy1.broker
BEAM_SECRET=App1Secret
TOKEN_MANAGER_DB_URL=./file.db
TOKEN_MANAGER_DB_PATH=./file.db
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ serde_json = "1.0"
serde = { version = "1", features = ["derive"] }
anyhow = { version = "1.0", default-features = false }
chrono = "0.4"
uuid = { version = "1.7.0", features = ["v4"] }
# Db
diesel = { version = "2.1.4", features = ["sqlite", "r2d2"] }
diesel_migrations = { version = "2.1.0", features = ["sqlite"] }
Expand Down
7 changes: 5 additions & 2 deletions migrations/2023-11-21-192332_token_manager/up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

CREATE TABLE tokens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
token_name TEXT NOT NULL,
token TEXT NOT NULL,
project_id TEXT NOT NULL,
bk TEXT NOT NULL,
status TEXT NOT NULL,
user_id TEXT NOT NULL
token_status TEXT NOT NULL,
project_status TEXT NOT NULL,
user_id TEXT NOT NULL,
token_created_at TEXT NOT NULL
)
3 changes: 0 additions & 3 deletions migrations/2023-11-30-093426_add_create_at_to_tokens/down.sql

This file was deleted.

3 changes: 0 additions & 3 deletions migrations/2023-11-30-093426_add_create_at_to_tokens/up.sql

This file was deleted.

6 changes: 3 additions & 3 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub struct Config {
pub addr: SocketAddr,

/// Url of the local beam proxy which is required to have sockets enabled
#[clap(long, env, default_value = "http://beam-proxy:8081")]
#[clap(long, env)]
pub beam_url: Url,

/// Beam api key
Expand All @@ -26,8 +26,8 @@ pub struct Config {
#[clap(long, env, value_parser=|id: &str| Ok::<_, Infallible>(AppId::new_unchecked(id)))]
pub beam_id: AppId,

#[clap(long, env)]
pub token_manager_db_url: String,
#[clap(long, env, default_value = "./file.db ")]
pub token_manager_db_path: String,
}

pub static BEAM_CLIENT: Lazy<BeamClient> = Lazy::new(|| BeamClient::new(
Expand Down
266 changes: 205 additions & 61 deletions src/db.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
use crate::config::CONFIG;
use crate::models::{NewToken, ScriptParams, TokenManager};
use axum::{async_trait, extract::{FromRef, FromRequestParts}, http::{request::Parts, StatusCode}, Json};
use diesel::prelude::*;
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
use diesel::result::Error;
use serde_json::json;
use tracing::{error, warn, info};
use anyhow::Result;
use tracing::{error, info, warn};

use crate::config::CONFIG;
use crate::schema::tokens::dsl::*;
use crate::schema::tokens;
use crate::enums::{OpalTokenStatus, OpalProjectStatus};
use crate::handlers::{check_project_status_request, fetch_project_tables_request, check_token_status_request};
use crate::models::{NewToken, TokenManager, TokenParams, TokenStatus};

const MIGRATIONS: EmbeddedMigrations = embed_migrations!();

pub fn setup_db() -> anyhow::Result<Pool<ConnectionManager<SqliteConnection>>> {
let pool = Pool::new(ConnectionManager::<SqliteConnection>::new(
&CONFIG.token_manager_db_url,
&CONFIG.token_manager_db_path,
))?;
info!("Running migrations");
pool.get()?.run_pending_migrations(MIGRATIONS).unwrap();
Expand All @@ -24,9 +31,9 @@ pub struct Db(PooledConnection<ConnectionManager<SqliteConnection>>);

#[async_trait]
impl<S> FromRequestParts<S> for Db
where
Pool<ConnectionManager<SqliteConnection>>: FromRef<S>,
S: Send + Sync,
where
Pool<ConnectionManager<SqliteConnection>>: FromRef<S>,
S: Send + Sync,
{
type Rejection = StatusCode;

Expand All @@ -38,11 +45,10 @@ where
}

impl Db {
pub fn save_token_db(&mut self, token: NewToken) {
use crate::schema::tokens;
pub fn save_token_db(&mut self, new_token: NewToken) {

match diesel::insert_into(tokens::table)
.values(&token)
.values(&new_token)
.on_conflict_do_nothing()
.execute(&mut self.0)
{
Expand All @@ -55,83 +61,221 @@ impl Db {
}
}

pub async fn check_project_status(
pub fn update_token_db(&mut self, token_update: NewToken) {


let target = tokens.filter(
user_id.eq(&token_update.user_id)
.and(project_id.eq(&token_update.project_id))
.and(bk.eq(&token_update.bk))
);

match diesel::update(target)
.set((
token.eq(token_update.token),
token_status.eq("UPDATED"),
token_created_at.eq(&token_update.token_created_at),
))
.execute(&mut self.0)
{
Ok(_) => {
info!("Token updated in DB");
}
Err(error) => {
warn!("Error updating token: {}", error);
}
}
}

pub fn update_token_status_db(&mut self, token_update: TokenStatus) {


let target = tokens.filter(
user_id.eq(&token_update.user_id)
.and(project_id.eq(&token_update.project_id))
.and(bk.eq(&token_update.bk))
);

match diesel::update(target)
.set((
token_status.eq(token_update.token_status),
))
.execute(&mut self.0)
{
Ok(_) => {
info!("Token status updated in DB");
}
Err(error) => {
warn!("Error updating token status: {}", error);
}
}
}

pub fn delete_project_db(&mut self,
project: String,
) {


let target = tokens.filter(
project_id.eq(&project)
);

match diesel::delete(target).execute(&mut self.0) {
Ok(_) => {
info!("Project and Tokens deleted from DB");
}
Err(error) => {
warn!("Error deleting token: {}", error);
}
}
}

pub fn delete_token_db(&mut self,
name: String,
) {


let target = tokens.filter(
token_name.eq(&name)
);

match diesel::delete(target).execute(&mut self.0) {
Ok(_) => {
info!("Tokens deleted from DB");
}
Err(error) => {
warn!("Error deleting token: {}", error);
}
}
}

pub fn get_token_name(&mut self, user: String, project: String) -> Result<Option<String>, Error> {


tokens
.filter(user_id.eq(user))
.filter(project_id.eq(project))
.select(token_name)
.first::<String>(&mut self.0)
.optional()
}

pub async fn check_token_status(
&mut self,
user: String,
bridgehead: String,
project: String,
) -> Result<Json<serde_json::Value>, (StatusCode, String)> {
use crate::schema::tokens::dsl::*;

match tokens

let mut token_status_json = json!({
"project_id": project.clone(),
"bk": bridgehead.clone(),
"user_id": user.clone(),
"token_created_at": "",
"project_status": OpalTokenStatus::NOTFOUND,
"token_status": OpalProjectStatus::NOTFOUND,
});

if let Ok(json_response) = check_project_status_request(project.clone(), bridgehead.clone()).await {
token_status_json["project_status"] = json_response.0["project_status"].clone();
} else {
error!("Error retrieving project status");
}

let token_name_response = match self.get_token_name(user.clone(), project.clone()) {
Ok(Some(name)) => name,
Ok(None) => return Ok(Json(token_status_json)),
Err(e) => return Err((StatusCode::INTERNAL_SERVER_ERROR, e.to_string())),
};

let records = match tokens
.filter(user_id.eq(&user))
.filter(bk.eq(&bridgehead))
.filter(project_id.eq(&project))
.select(TokenManager::as_select())
.load::<TokenManager>(&mut self.0)
{
Ok(records) => {
if !records.is_empty() {
info!("Project found with project_id: {:?}", &records);
let response = json!({
"status": "success",
"data": records
});
Ok(Json(response))
} else {
info!("Project not found with project_id: {}", project);
let error_response = r#"{
"status": "error",
"message": "Project not found with project_id"
}"#;
Err((StatusCode::NOT_FOUND, error_response.into()))
}
Ok(records) if !records.is_empty() => records,
Ok(_) => {
info!("Token not found with user_id: {}", &user);
return Ok(Json(token_status_json));
}
Err(err) => {
error!("Error calling DB: {}", err);
Err((
StatusCode::INTERNAL_SERVER_ERROR,
"Cannot connect to database".into(),
))
return Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string()));
}
};

let record = &records[0];
token_status_json["token_created_at"] = json!(record.token_created_at);
let token_value = json!(record.token).as_str().unwrap_or_default().to_string();

if let Ok(json_response) = check_token_status_request(user.clone(), bridgehead.clone(), project.clone(), token_name_response.clone(), token_value.clone()).await {
token_status_json["token_status"] = json_response.0["token_status"].clone();

let new_token_status = TokenStatus {
project_id: &project.clone(),
bk: &bridgehead.clone(),
token_status: OpalTokenStatus::CREATED.as_str(),
user_id: &user.clone(),
};
self.update_token_status_db(new_token_status);

} else {
error!("Error retrieving token status");
}
Ok(Json(token_status_json))
}

pub async fn generate_user_script(&mut self, query: ScriptParams) -> Result<String, String> {
use crate::schema::tokens::dsl::*;
pub async fn generate_user_script(&mut self, query: TokenParams) -> Result<String, String> {
let tables_result = fetch_project_tables_request(query.clone()).await;
let mut script_lines = Vec::new();

let records = tokens
.filter(project_id.eq(&query.project)) // Match project_id from the query parameters
.filter(user_id.eq(&query.user)) // Match user_id from the query parameters
.select(TokenManager::as_select())
.load::<TokenManager>(&mut self.0);

match records {
Ok(records) => {
let mut script_lines = Vec::new();
if !records.is_empty() {
for record in records {
info!("Records Extracted: {:?}", record);
script_lines.push(format!("builder$append(server='DockerOpal', url='https://{}/opal/', token='{}', table='{}', driver='OpalDriver')",
record.bk , record.token, record.project_id
));
}
if let Ok(tables) = tables_result {
info!("Result from status_project_from_beam: {:?}", tables);

let script = generate_r_script(script_lines);
info!("Script Generated: {:?}", script);
Ok(script)
} else {
info!("No records were found");
Ok("No records found for the given project and user.".into())
let records = tokens
.filter(project_id.eq(&query.project_id))
.filter(user_id.eq(&query.user_id))
.select(TokenManager::as_select())
.load::<TokenManager>(&mut self.0);

match records {
Ok(records) => {
if !records.is_empty() {
for record in &records {
for table in &tables {
script_lines.push(format!(
"builder$append(server='{}', url='https://{}/opal/', token='{}', table='{}', driver='OpalDriver')",
record.bk, record.bk, record.token, table
));
}
}
let script = generate_r_script(script_lines);
Ok(script)
} else {
info!("No records were found");
Ok("No records found for the given project and user.".into())
}
}
Err(err) => {
error!("Error loading records: {}", err);
Err(format!("Error loading records: {}", err))
}
}
Err(err) => {
error!("Error loading records: {}", err);
Err(format!("Error loading records: {}", err))
} else {
if let Err(e) = tables_result {
info!("Error in status_project_from_beam: {:?}", e);
}
Err("Error obtaining table names.".into())
}
}
}

fn generate_r_script(script_lines: Vec<String>) -> String {
let mut builder_script = String::from(
r#"library(DSI)
r#"library(DSI)
library(DSOpal)
library(dsBaseClient)
set_config(use_proxy(url="http://beam-connect", port=8062))
Expand Down
Loading
Loading