Added a feature to create temporary users

- Token verification simplified
This commit is contained in:
Shiroyasha 2024-06-18 16:01:23 +03:00
parent 4bd9a2ab2e
commit 7594e3d615
Signed by: shiroyashik
GPG key ID: E4953D3940D7860A
7 changed files with 60 additions and 45 deletions

View file

@ -3,12 +3,7 @@ use std::{str::FromStr, sync::Arc};
use crate::utils::*; use crate::utils::*;
use anyhow::anyhow; use anyhow::anyhow;
use axum::{ use axum::{
async_trait, debug_handler, async_trait, debug_handler, extract::{FromRequestParts, Query, State}, http::{request::Parts, StatusCode}, response::{IntoResponse, Response}, routing::{get, post}, Json, Router
extract::{FromRequestParts, Query, State},
http::{request::Parts, StatusCode},
response::{IntoResponse, Response},
routing::get,
Router,
}; };
use dashmap::DashMap; use dashmap::DashMap;
use ring::digest::{self, digest}; use ring::digest::{self, digest};
@ -24,6 +19,11 @@ pub fn router() -> Router<AppState> {
.route("/verify", get(verify)) .route("/verify", get(verify))
} }
pub fn router_v1() -> Router<AppState> {
Router::new()
.route("/create", post(create_user))
}
// Web // Web
#[derive(Deserialize)] #[derive(Deserialize)]
struct Id { struct Id {
@ -83,7 +83,10 @@ async fn verify(
} }
} }
pub async fn status(Token(token): Token, State(state): State<AppState>) -> Response { pub async fn status(
Token(token): Token,
State(state): State<AppState>
) -> Response {
match token { match token {
Some(token) => { Some(token) => {
if state.user_manager.is_authenticated(&token) { if state.user_manager.is_authenticated(&token) {
@ -98,6 +101,21 @@ pub async fn status(Token(token): Token, State(state): State<AppState>) -> Respo
} }
} }
} }
pub async fn create_user(
Token(token): Token,
State(state): State<AppState>,
Json(json): Json<Userinfo>
) -> Response {
debug!("Json: {json:?}");
match state.config.lock().await.clone().verify_token(&token) {
Ok(_) => {},
Err(e) => return e,
}
state.user_manager.insert_user(json.uuid, json);
(StatusCode::OK, "ok".to_string()).into_response()
}
// Web End // Web End
// It's an extractor that pulls a token from the Header. // It's an extractor that pulls a token from the Header.
@ -126,6 +144,7 @@ where
// End Extractor // End Extractor
#[derive(Debug, Clone, PartialEq, Deserialize)] #[derive(Debug, Clone, PartialEq, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum AuthSystem { pub enum AuthSystem {
Internal, Internal,
ElyBy, ElyBy,
@ -233,7 +252,8 @@ pub struct UManager {
registered: Arc<DashMap<Uuid, Userinfo>>, registered: Arc<DashMap<Uuid, Userinfo>>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Userinfo { pub struct Userinfo {
pub username: String, pub username: String,
pub uuid: Uuid, pub uuid: Uuid,
@ -278,7 +298,7 @@ impl UManager {
pub fn is_authenticated(&self, token: &String) -> bool { pub fn is_authenticated(&self, token: &String) -> bool {
self.authenticated.contains_key(token) self.authenticated.contains_key(token)
} }
pub fn is_registered(&self, uuid: &Uuid) -> bool { pub fn _is_registered(&self, uuid: &Uuid) -> bool {
self.registered.contains_key(uuid) self.registered.contains_key(uuid)
} }
pub fn remove(&self, uuid: &Uuid) { pub fn remove(&self, uuid: &Uuid) {

View file

@ -14,16 +14,22 @@ pub struct Config {
} }
impl Config { impl Config {
pub fn verify_token(&self, suspicious: &str) -> bool { pub fn verify_token(&self, suspicious: &Option<String>) -> Result<axum::response::Response, axum::response::Response> {
use axum::{http::StatusCode, response::IntoResponse};
match &self.token { match &self.token {
Some(t) => { Some(token) => {
if t == suspicious { match suspicious {
true Some(suspicious) => {
if token == suspicious {
return Ok((StatusCode::OK, "ok".to_string()).into_response())
} else { } else {
false return Err((StatusCode::UNAUTHORIZED, "wrong token".to_string()).into_response())
} }
}, },
None => false None => return Err((StatusCode::UNAUTHORIZED, "unauthorized".to_string()).into_response())
}
},
None => return Err((StatusCode::LOCKED, "token doesnt defined".to_string()).into_response()),
} }
} }
} }

View file

@ -94,9 +94,13 @@ async fn main() -> Result<()> {
} }
}); });
let v1 = Router::new()
.nest("/", ws::http2ws_router())
.nest("/user", api_auth::router_v1());
let api = Router::new() let api = Router::new()
.nest("//auth", api_auth::router()) .nest("//auth", api_auth::router())
.nest("/v1", ws::http_router()) .nest("/v1", v1)
.route("/limits", get(api_info::limits)) .route("/limits", get(api_info::limits))
.route("/version", get(api_info::version)) .route("/version", get(api_info::version))
.route("/motd", get(api_info::motd)) .route("/motd", get(api_info::motd))

View file

@ -4,7 +4,7 @@ use axum::{
extract::{Path, State}, extract::{Path, State},
Json, Json,
}; };
use tracing::{debug, warn}; use tracing::debug;
use serde_json::{json, Value}; use serde_json::{json, Value};
use tokio::{ use tokio::{
fs, fs,

View file

@ -27,15 +27,9 @@ async fn verify(
Token(token): Token, Token(token): Token,
State(state): State<AppState>, State(state): State<AppState>,
) -> Response { ) -> Response {
match token { state.config.lock().await.clone()
Some(t) => { .verify_token(&token)
if !state.config.lock().await.verify_token(&t) { .unwrap_or_else(|x| x)
return (StatusCode::UNAUTHORIZED, "wrong token".to_string()).into_response()
}
},
None => return (StatusCode::UNAUTHORIZED, "unauthorized".to_string()).into_response(),
}
(StatusCode::OK, "ok".to_string()).into_response()
} }
async fn raw( async fn raw(
@ -45,13 +39,9 @@ async fn raw(
body: String, body: String,
) -> Response { ) -> Response {
debug!(body = body); debug!(body = body);
match token { match state.config.lock().await.clone().verify_token(&token) {
Some(t) => { Ok(_) => {},
if !state.config.lock().await.verify_token(&t) { Err(e) => return e,
return (StatusCode::UNAUTHORIZED, "wrong token".to_string()).into_response()
}
},
None => return (StatusCode::UNAUTHORIZED, "unauthorized".to_string()).into_response(),
} }
let payload = match hex::decode(body) { let payload = match hex::decode(body) {
Ok(v) => v, Ok(v) => v,
@ -85,13 +75,9 @@ async fn sub_raw(
body: String, body: String,
) -> Response { ) -> Response {
debug!(body = body); debug!(body = body);
match token { match state.config.lock().await.clone().verify_token(&token) {
Some(t) => { Ok(_) => {},
if !state.config.lock().await.verify_token(&t) { Err(e) => return e,
return (StatusCode::UNAUTHORIZED, "wrong token".to_string()).into_response()
}
},
None => return (StatusCode::UNAUTHORIZED, "unauthorized".to_string()).into_response(),
} }
let payload = match hex::decode(body) { let payload = match hex::decode(body) {
Ok(v) => v, Ok(v) => v,

View file

@ -5,4 +5,4 @@ mod http;
pub use types::C2SMessage; pub use types::C2SMessage;
pub use types::S2CMessage; pub use types::S2CMessage;
pub use websocket::handler; pub use websocket::handler;
pub use http::router as http_router; pub use http::router as http2ws_router;

View file

@ -27,7 +27,6 @@ pub async fn handler(ws: WebSocketUpgrade, State(state): State<AppState>) -> Res
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct WSUser { struct WSUser {
username: String, username: String,
token: String,
uuid: Uuid, uuid: Uuid,
} }
@ -87,7 +86,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
match state.user_manager.get(&token) { // The principle is simple: if there is no token in authenticated, then it's "dirty hacker" :D match state.user_manager.get(&token) { // The principle is simple: if there is no token in authenticated, then it's "dirty hacker" :D
Some(t) => { Some(t) => {
//username = t.username.clone(); //username = t.username.clone();
owner = Some(WSUser { username: t.username.clone(), token, uuid: t.uuid }); owner = Some(WSUser { username: t.username.clone(), uuid: t.uuid });
state.session.insert(t.uuid, mtx.clone()); state.session.insert(t.uuid, mtx.clone());
msg = Message::Binary(S2CMessage::Auth.to_vec()); msg = Message::Binary(S2CMessage::Auth.to_vec());
match state.broadcasts.get(&t.uuid) { match state.broadcasts.get(&t.uuid) {