moved backend into backend directory

This commit is contained in:
Colin McKechney
2023-04-28 01:10:08 -04:00
parent 7f1e4a0808
commit cc1c370e56
5 changed files with 0 additions and 0 deletions

1916
backend/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

20
backend/Cargo.toml Normal file
View File

@@ -0,0 +1,20 @@
[package]
name = "adv_db"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-cors = "0.6.4"
actix-identity = "0.5.2"
actix-session = { version = "0.7.2", features = ["cookie-session"] }
actix-web = "4.3.1"
chrono = "0.4.24"
env_logger = "0.10.0"
log = "0.4.17"
oracle = "0.5.7"
rand = "0.8.5"
serde = { version = "1.0.160", features = ["derive"] }
serde_json = "1.0.96"
sha2 = "0.10.6"

2
backend/src/api/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod user;

162
backend/src/api/user.rs Normal file
View File

@@ -0,0 +1,162 @@
use sha2::{Sha256, Digest};
use rand::{prelude::Rng, distributions::Alphanumeric };
use oracle::{Connection, Error};
use log::{info, warn, error};
use actix_identity::Identity;
use actix_web::{web, Responder, HttpRequest, HttpMessage, HttpResponse};
use serde::{Deserialize, Serialize};
static SQL_USERNAME: &str = "group09_user";
static SQL_PASSWORD: &str = "group09_user";
static SALT_LEN: usize = 16;
#[derive(Deserialize, Serialize, Debug, Default)]
pub struct Entry {
net_id: String,
password: String
}
#[derive(Deserialize, Serialize, Debug, Default)]
pub struct User {
id: String,
first_name: String,
last_name: String
}
#[derive(Deserialize, Serialize, Debug, Default)]
pub struct NewUser {
netid: String,
password: String,
first_name: String,
last_name: String
}
pub async fn login(request: HttpRequest, body: web::Json<Entry>) -> impl Responder {
//TODO: finish login, for now will simply login for everyone
let net_id: &str = body.net_id.as_str();
let password: &str = body.password.as_str();
//Identity::login(&request.extensions(), "User1".into());
println!("{:?}", request);
println!("{:?}", body);
match authenticate(net_id, password) {
Some(user) => {
Identity::login(&request.extensions(), net_id.into());
web::Json(user);
HttpResponse::Ok()
},
None => {
web::Json(User::default());
HttpResponse::Unauthorized()
}
}
}
pub async fn logout(user: Identity) -> impl Responder {
user.logout();
HttpResponse::Ok()
}
pub async fn signup(request: HttpRequest, body: web::Json<NewUser>) -> impl Responder {
let body = body.into_inner();
match create_user(body.netid.as_str(), body.password.as_str(), body.first_name.as_str(), body.last_name.as_str()) {
Ok(_) => {
Identity::login(&request.extensions(), body.netid.clone());
web::Json(User { id: body.netid, first_name: body.first_name, last_name: body.last_name});
HttpResponse::Ok()
}
Err(e) => {
error!("Error creating new user: {}", e);
HttpResponse::InternalServerError()
}
}
}
fn authenticate(username: &str, password: &str) -> Option<User> {
info!("Authenticating user: {}", username);
let conn = match Connection::connect(SQL_USERNAME,SQL_PASSWORD, ""){
Ok(c) => c,
Err(e) => {
error!("unable to open connection to server: {}", e);
return None;
}
};
let mut stmt = match conn.statement("select * from student where net_id = :1").build(){
Ok(s) => s,
Err(e) => {
error!("unable to build statement: {}", e);
return None;
}
};
let row = stmt.query_row_as::<(String, String, String, String, String)>(&[&username]).unwrap_or_default();
let true_pword = row.3;
let salt = row.4;
let mut hasher = Sha256::new();
hasher.update(password);
hasher.update(salt);
let hash = hasher.finalize();
let mut tmp: String = String::new();
for value in hash{
tmp += &format!("{:x}", value);
}
conn.close().unwrap_or_default();
if true_pword.eq(&tmp) {
info!("User {} successfully authenticated", username);
Some( User { id: row.0, first_name: row.1,last_name: row.2} )
}
else{
warn!("User {} failed authentication", username);
None
}
}
fn create_user(username: &str, password: &str, first_name: &str, last_name: &str) -> Result<(), Error> {
info!("Creating user: {}", username);
let conn = Connection::connect(SQL_USERNAME, SQL_PASSWORD, "")?;
let mut stmt = conn.statement("insert into student values(:net_id, :first_name, :last_name, :password, :salt)").build()?;
let salt: String = rand::thread_rng().sample_iter(&Alphanumeric).take(SALT_LEN).map(char::from).collect();
let mut hasher = Sha256::new();
hasher.update(&password);
hasher.update(&salt);
let hash = hasher.finalize();
let mut hash_string = String::new();
for value in hash{
hash_string += &format!("{:x}", value);
}
match stmt.execute_named(&[("net_id", &username), ("first_name", &first_name), ("last_name", &last_name), ("password", &hash_string), ("salt", &salt)]) {
Ok(_) => {
info!("User {} successfully created", username);
conn.commit()?;
},
Err(_) => {
warn!("Failed to create user {}", username);
conn.rollback()?;
}
};
conn.close()?;
Ok(())
}

70
backend/src/main.rs Normal file
View File

@@ -0,0 +1,70 @@
use log::{info, warn, error};
use env_logger::Env;
use actix_web::{web, get, post, web::Json, App, HttpResponse, HttpServer, Responder, middleware, cookie::Key};
use serde::{Deserialize, Serialize};
use actix_cors::Cors;
use actix_identity::IdentityMiddleware;
use actix_session::{SessionMiddleware, storage::CookieSessionStore};
mod api;
static PORT: u16 = 5000;
const ALLOWED_ORIGIN: &str = "http://localhost";
#[derive(Default, Debug, Serialize, Deserialize, Clone)]
struct Login {
net_id: String,
password: String,
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
//init logging system
let env = Env::default().filter_or("LOG_LEVEL", "info");
env_logger::init_from_env(env);
let secret_key = Key::generate();
let _ = HttpServer::new(move || {
App::new()
.wrap(middleware::Logger::default())
.wrap(
Cors::default()
.allowed_origin(ALLOWED_ORIGIN)
.allowed_methods(vec!["GET","POST","DELETE"])
.supports_credentials()
)
.wrap(IdentityMiddleware::default())
.wrap(SessionMiddleware::new(CookieSessionStore::default(), secret_key.clone()))
.service(
web::scope("/api")
.service(
web::resource("/auth")
.route(web::post().to(api::user::login))
.route(web::delete().to(api::user::logout))
)
.service(
web::resource("/signup")
.route(web::post().to(api::user::signup))
)
.route("/", web::get().to(api_index))
)
.route("/", web::get().to(index))
})
.bind(("127.0.0.1", PORT))?
.run()
.await;
Ok(())
}
async fn api_index() -> impl Responder {
HttpResponse::Ok().body("api")
}
async fn index() -> impl Responder {
HttpResponse::Ok().body("/")
}