mirror of
https://github.com/house-of-vanity/OutFleet.git
synced 2025-10-26 02:09:07 +00:00
URI works on android. Shadowsocks doesn't work on iPhone. it's ok - will be fixed.
This commit is contained in:
136
src/web/handlers/client_configs.rs
Normal file
136
src/web/handlers/client_configs.rs
Normal file
@@ -0,0 +1,136 @@
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
http::StatusCode,
|
||||
response::Json,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::database::repository::InboundUsersRepository;
|
||||
use crate::services::UriGeneratorService;
|
||||
use crate::web::AppState;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct IncludeUrisQuery {
|
||||
#[serde(default)]
|
||||
pub include_uris: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct ClientConfigResponse {
|
||||
pub user_id: Uuid,
|
||||
pub server_name: String,
|
||||
pub inbound_tag: String,
|
||||
pub protocol: String,
|
||||
pub uri: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub qr_code: Option<String>,
|
||||
}
|
||||
|
||||
/// Generate URI for specific user and inbound
|
||||
pub async fn get_user_inbound_config(
|
||||
State(app_state): State<AppState>,
|
||||
Path((user_id, inbound_id)): Path<(Uuid, Uuid)>,
|
||||
) -> Result<Json<ClientConfigResponse>, StatusCode> {
|
||||
let repo = InboundUsersRepository::new(app_state.db.connection().clone());
|
||||
let uri_service = UriGeneratorService::new();
|
||||
|
||||
// Get client configuration data
|
||||
let config_data = repo.get_client_config_data(user_id, inbound_id)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
let config_data = config_data.ok_or(StatusCode::NOT_FOUND)?;
|
||||
|
||||
// Generate URI
|
||||
let client_config = uri_service.generate_client_config(user_id, &config_data)
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
let response = ClientConfigResponse {
|
||||
user_id: client_config.user_id,
|
||||
server_name: client_config.server_name,
|
||||
inbound_tag: client_config.inbound_tag,
|
||||
protocol: client_config.protocol,
|
||||
uri: client_config.uri,
|
||||
qr_code: client_config.qr_code,
|
||||
};
|
||||
|
||||
Ok(Json(response))
|
||||
}
|
||||
|
||||
/// Generate all URIs for a user
|
||||
pub async fn get_user_configs(
|
||||
State(app_state): State<AppState>,
|
||||
Path(user_id): Path<Uuid>,
|
||||
) -> Result<Json<Vec<ClientConfigResponse>>, StatusCode> {
|
||||
let repo = InboundUsersRepository::new(app_state.db.connection().clone());
|
||||
let uri_service = UriGeneratorService::new();
|
||||
|
||||
// Get all client configuration data for user
|
||||
let configs_data = repo.get_all_client_configs_for_user(user_id)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
let mut responses = Vec::new();
|
||||
|
||||
for config_data in configs_data {
|
||||
match uri_service.generate_client_config(user_id, &config_data) {
|
||||
Ok(client_config) => {
|
||||
responses.push(ClientConfigResponse {
|
||||
user_id: client_config.user_id,
|
||||
server_name: client_config.server_name,
|
||||
inbound_tag: client_config.inbound_tag,
|
||||
protocol: client_config.protocol,
|
||||
uri: client_config.uri,
|
||||
qr_code: client_config.qr_code,
|
||||
});
|
||||
},
|
||||
Err(_) => {
|
||||
// Log error but continue with other configs
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Json(responses))
|
||||
}
|
||||
|
||||
/// Get all URIs for all users of a specific inbound
|
||||
pub async fn get_inbound_configs(
|
||||
State(app_state): State<AppState>,
|
||||
Path((server_id, inbound_id)): Path<(Uuid, Uuid)>,
|
||||
) -> Result<Json<Vec<ClientConfigResponse>>, StatusCode> {
|
||||
let repo = InboundUsersRepository::new(app_state.db.connection().clone());
|
||||
let uri_service = UriGeneratorService::new();
|
||||
|
||||
// Get all users for this inbound
|
||||
let inbound_users = repo.find_active_by_inbound_id(inbound_id)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
let mut responses = Vec::new();
|
||||
|
||||
for inbound_user in inbound_users {
|
||||
// Get client configuration data for each user
|
||||
if let Ok(Some(config_data)) = repo.get_client_config_data(inbound_user.user_id, inbound_id).await {
|
||||
match uri_service.generate_client_config(inbound_user.user_id, &config_data) {
|
||||
Ok(client_config) => {
|
||||
responses.push(ClientConfigResponse {
|
||||
user_id: client_config.user_id,
|
||||
server_name: client_config.server_name,
|
||||
inbound_tag: client_config.inbound_tag,
|
||||
protocol: client_config.protocol,
|
||||
uri: client_config.uri,
|
||||
qr_code: client_config.qr_code,
|
||||
});
|
||||
},
|
||||
Err(_) => {
|
||||
// Log error but continue with other configs
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Json(responses))
|
||||
}
|
||||
@@ -2,8 +2,10 @@ pub mod users;
|
||||
pub mod servers;
|
||||
pub mod certificates;
|
||||
pub mod templates;
|
||||
pub mod client_configs;
|
||||
|
||||
pub use users::*;
|
||||
pub use servers::*;
|
||||
pub use certificates::*;
|
||||
pub use templates::*;
|
||||
pub use templates::*;
|
||||
pub use client_configs::*;
|
||||
@@ -12,6 +12,8 @@ use crate::database::entities::user::{CreateUserDto, UpdateUserDto, Model as Use
|
||||
use crate::database::repository::UserRepository;
|
||||
use crate::web::AppState;
|
||||
|
||||
use super::client_configs::IncludeUrisQuery;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct PaginationQuery {
|
||||
#[serde(default = "default_page")]
|
||||
@@ -197,8 +199,10 @@ pub async fn delete_user(
|
||||
pub async fn get_user_access(
|
||||
State(app_state): State<AppState>,
|
||||
Path(user_id): Path<Uuid>,
|
||||
Query(query): Query<IncludeUrisQuery>,
|
||||
) -> Result<Json<Vec<serde_json::Value>>, StatusCode> {
|
||||
use crate::database::repository::InboundUsersRepository;
|
||||
use crate::services::UriGeneratorService;
|
||||
|
||||
let inbound_users_repo = InboundUsersRepository::new(app_state.db.connection().clone());
|
||||
|
||||
@@ -207,17 +211,51 @@ pub async fn get_user_access(
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
let response: Vec<serde_json::Value> = access_list
|
||||
.into_iter()
|
||||
.map(|access| serde_json::json!({
|
||||
"id": access.id,
|
||||
"user_id": access.user_id,
|
||||
"server_inbound_id": access.server_inbound_id,
|
||||
"xray_user_id": access.xray_user_id,
|
||||
"level": access.level,
|
||||
"is_active": access.is_active,
|
||||
}))
|
||||
.collect();
|
||||
let mut response: Vec<serde_json::Value> = Vec::new();
|
||||
|
||||
if query.include_uris {
|
||||
let uri_service = UriGeneratorService::new();
|
||||
|
||||
for access in access_list {
|
||||
let mut access_json = serde_json::json!({
|
||||
"id": access.id,
|
||||
"user_id": access.user_id,
|
||||
"server_inbound_id": access.server_inbound_id,
|
||||
"xray_user_id": access.xray_user_id,
|
||||
"level": access.level,
|
||||
"is_active": access.is_active,
|
||||
});
|
||||
|
||||
// Try to get client config and generate URI
|
||||
if access.is_active {
|
||||
if let Ok(Some(config_data)) = inbound_users_repo
|
||||
.get_client_config_data(user_id, access.server_inbound_id)
|
||||
.await {
|
||||
|
||||
if let Ok(client_config) = uri_service.generate_client_config(user_id, &config_data) {
|
||||
access_json["uri"] = serde_json::Value::String(client_config.uri);
|
||||
access_json["protocol"] = serde_json::Value::String(client_config.protocol);
|
||||
access_json["server_name"] = serde_json::Value::String(client_config.server_name);
|
||||
access_json["inbound_tag"] = serde_json::Value::String(client_config.inbound_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.push(access_json);
|
||||
}
|
||||
} else {
|
||||
response = access_list
|
||||
.into_iter()
|
||||
.map(|access| serde_json::json!({
|
||||
"id": access.id,
|
||||
"user_id": access.user_id,
|
||||
"server_inbound_id": access.server_inbound_id,
|
||||
"xray_user_id": access.xray_user_id,
|
||||
"level": access.level,
|
||||
"is_active": access.is_active,
|
||||
}))
|
||||
.collect();
|
||||
}
|
||||
|
||||
Ok(Json(response))
|
||||
}
|
||||
Reference in New Issue
Block a user