mirror of
https://github.com/Arcadia-Solutions/arcadia.git
synced 2025-12-20 08:49:36 -06:00
fixed db stuff, added user provider
This commit is contained in:
2
.env
2
.env
@@ -8,7 +8,7 @@ ACTIX_PORT=8080
|
||||
JWT_SECRET=sensitivejwtsecret
|
||||
PASSWORD_HASH_SECRET=sensitivepasswordhashsecret
|
||||
|
||||
# Postgre config
|
||||
# postgre config
|
||||
|
||||
POSTGRESQL_DATABASE=arcadia
|
||||
POSTGRESQL_USER=arcadia
|
||||
|
||||
29
Cargo.lock
generated
29
Cargo.lock
generated
@@ -253,6 +253,7 @@ dependencies = [
|
||||
"argon2",
|
||||
"chrono",
|
||||
"dotenv",
|
||||
"futures",
|
||||
"jsonwebtoken",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -883,6 +884,21 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.31"
|
||||
@@ -955,6 +971,17 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.31"
|
||||
@@ -973,8 +1000,10 @@ version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
|
||||
@@ -18,3 +18,4 @@ chrono = { version = "0.4", features = ["serde"] }
|
||||
uuid = { version = "1.15.1", features = ["serde", "v4"] }
|
||||
jsonwebtoken = "9.3.1"
|
||||
argon2 = "0.5.3"
|
||||
futures = "0.3"
|
||||
|
||||
@@ -3,12 +3,13 @@ Arcadia's backend
|
||||
|
||||
## Setup
|
||||
|
||||
Copy `.env` to `.env.local` and replace the values with yours
|
||||
- Copy `.env` to `.env.local` and replace the values with yours
|
||||
|
||||
- The `docker/` folder contains some containers to various services used by `actix-index`. Feel free to use these or substitutes
|
||||
|
||||
### Optional
|
||||
- Create a database with the name that is specified by the env variable `POSTGRESQL_DATABASE`
|
||||
|
||||
The `docker/` folder contains some containers to various services used by `actix-index`. Feel free to use these or a local install of them
|
||||
- install `sqlx-cli` and run the database migrations : `sqlx migrate run`
|
||||
|
||||
|
||||
## Developing
|
||||
|
||||
@@ -29,7 +29,7 @@ CREATE TABLE users
|
||||
requests_voted BIGINT NOT NULL DEFAULT 0,
|
||||
average_seeding_time BIGINT NOT NULL DEFAULT 0,
|
||||
invited BIGINT NOT NULL DEFAULT 0,
|
||||
invites INT NOT NULL DEFAULT 0
|
||||
invites SMALLINT NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE invitations
|
||||
|
||||
@@ -55,7 +55,7 @@ pub async fn login(pool: web::Data<PgPool>, user_login: web::Json<Login>) -> Htt
|
||||
expiration_date = expiration_date + Duration::days(365);
|
||||
}
|
||||
let user_claims = Claims {
|
||||
sub: user.username,
|
||||
sub: user.id,
|
||||
exp: expiration_date.timestamp() as usize,
|
||||
};
|
||||
let token = encode(
|
||||
|
||||
@@ -2,13 +2,16 @@ use actix_web::{HttpResponse, web};
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
models::invitation::SentInvitation, repositories::invitation_repository::create_invitation,
|
||||
models::{invitation::SentInvitation, user::User},
|
||||
repositories::invitation_repository::create_invitation,
|
||||
};
|
||||
|
||||
pub async fn send_invitation(
|
||||
invitation: web::Json<SentInvitation>,
|
||||
pool: web::Data<PgPool>,
|
||||
user: User,
|
||||
) -> HttpResponse {
|
||||
println!("{}", user.id);
|
||||
match create_invitation(&pool, &invitation).await {
|
||||
Ok(user) => HttpResponse::Created().json(serde_json::json!(user)),
|
||||
Err(err) => HttpResponse::InternalServerError().json(serde_json::json!({
|
||||
|
||||
@@ -32,7 +32,7 @@ pub struct User {
|
||||
pub requests_voted: i64,
|
||||
pub average_seeding_time: i64, //in seconds
|
||||
pub invited: i64,
|
||||
pub invites: i8,
|
||||
pub invites: i16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
@@ -52,6 +52,6 @@ pub struct Login {
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Claims {
|
||||
pub sub: String,
|
||||
pub sub: i32,
|
||||
pub exp: usize,
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
use crate::models::user::{Login, Register, User};
|
||||
use actix_web::web;
|
||||
use crate::models::user::{Claims, Login, Register, User};
|
||||
use actix_web::{FromRequest, HttpRequest, dev::Payload, web};
|
||||
use argon2::{
|
||||
Argon2,
|
||||
password_hash::{PasswordHash, PasswordVerifier},
|
||||
};
|
||||
use futures::future::{BoxFuture, Ready, err, ok};
|
||||
use jsonwebtoken::{DecodingKey, Validation, decode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::PgPool;
|
||||
use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
use std::{env, error::Error};
|
||||
|
||||
pub async fn create_user(
|
||||
pool: &web::Data<PgPool>,
|
||||
@@ -76,3 +79,43 @@ pub async fn find_user_with_password(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// user provider
|
||||
impl FromRequest for User {
|
||||
type Error = actix_web::Error;
|
||||
type Future = BoxFuture<'static, Result<Self, Self::Error>>;
|
||||
|
||||
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
|
||||
let pool = req.app_data::<PgPool>().cloned();
|
||||
let auth_header = req.headers().get("Authorization").cloned();
|
||||
|
||||
Box::pin(async move {
|
||||
if let (Some(pool), Some(auth_value)) = (pool, auth_header) {
|
||||
if let Ok(auth_str) = auth_value.to_str() {
|
||||
if auth_str.starts_with("Bearer ") {
|
||||
let token = &auth_str[7..];
|
||||
let decoding_key =
|
||||
DecodingKey::from_secret(env::var("JWT_SECRET").unwrap().as_ref());
|
||||
let validation = Validation::default();
|
||||
|
||||
if let Ok(token_data) = decode::<Claims>(token, &decoding_key, &validation)
|
||||
{
|
||||
let user_id = token_data.claims.sub;
|
||||
|
||||
let query = "SELECT id, username, email FROM users WHERE id = $1";
|
||||
let user = sqlx::query_as::<_, User>(query)
|
||||
.bind(user_id)
|
||||
.fetch_one(&pool)
|
||||
.await;
|
||||
|
||||
return user.map_err(|_| {
|
||||
actix_web::error::ErrorUnauthorized("User not found")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(actix_web::error::ErrorUnauthorized("Invalid token"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ pub async fn create_invitation(
|
||||
sqlx::Error::Database(db_error) => db_error.message().to_string(),
|
||||
_ => e.to_string(),
|
||||
};
|
||||
Err(format!("User not found").into())
|
||||
Err(format!("could not send invite").into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user