user domains API, .value on input, fix flex sizing
This commit is contained in:
@@ -93,6 +93,7 @@ enum HandlerType {
|
||||
CreateDomain,
|
||||
UpdateDomain,
|
||||
DeleteDomain,
|
||||
GetUserDomains,
|
||||
}
|
||||
|
||||
impl GurtHandler for AppHandler {
|
||||
@@ -128,6 +129,7 @@ impl GurtHandler for AppHandler {
|
||||
HandlerType::RedeemInvite => handle_authenticated!(ctx, app_state, auth_routes::redeem_invite),
|
||||
HandlerType::CreateDomainInvite => handle_authenticated!(ctx, app_state, auth_routes::create_domain_invite),
|
||||
HandlerType::RedeemDomainInvite => handle_authenticated!(ctx, app_state, auth_routes::redeem_domain_invite),
|
||||
HandlerType::GetUserDomains => handle_authenticated!(ctx, app_state, routes::get_user_domains),
|
||||
HandlerType::CreateDomain => {
|
||||
// Check rate limit first
|
||||
if let Some(ref rate_limit_state) = rate_limit_state {
|
||||
@@ -205,6 +207,7 @@ pub async fn start(cli: crate::Cli) -> std::io::Result<()> {
|
||||
.route(Route::post("/auth/redeem-invite"), AppHandler { app_state: app_state.clone(), rate_limit_state: None, handler_type: HandlerType::RedeemInvite })
|
||||
.route(Route::post("/auth/create-domain-invite"), AppHandler { app_state: app_state.clone(), rate_limit_state: None, handler_type: HandlerType::CreateDomainInvite })
|
||||
.route(Route::post("/auth/redeem-domain-invite"), AppHandler { app_state: app_state.clone(), rate_limit_state: None, handler_type: HandlerType::RedeemDomainInvite })
|
||||
.route(Route::get("/auth/domains"), AppHandler { app_state: app_state.clone(), rate_limit_state: None, handler_type: HandlerType::GetUserDomains })
|
||||
.route(Route::post("/domain"), AppHandler { app_state: app_state.clone(), rate_limit_state: Some(rate_limit_state), handler_type: HandlerType::CreateDomain })
|
||||
.route(Route::put("/domain/*"), AppHandler { app_state: app_state.clone(), rate_limit_state: None, handler_type: HandlerType::UpdateDomain })
|
||||
.route(Route::delete("/domain/*"), AppHandler { app_state: app_state.clone(), rate_limit_state: None, handler_type: HandlerType::DeleteDomain });
|
||||
|
||||
@@ -101,3 +101,19 @@ pub(crate) struct DomainList {
|
||||
pub(crate) domain: String,
|
||||
pub(crate) taken: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub(crate) struct UserDomain {
|
||||
pub(crate) name: String,
|
||||
pub(crate) tld: String,
|
||||
pub(crate) ip: String,
|
||||
pub(crate) status: String,
|
||||
pub(crate) denial_reason: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct UserDomainResponse {
|
||||
pub(crate) domains: Vec<UserDomain>,
|
||||
pub(crate) page: u32,
|
||||
pub(crate) limit: u32,
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ pub(crate) async fn create_logic(domain: Domain, user_id: i32, app: &AppState) -
|
||||
}
|
||||
|
||||
let existing_count: i64 = sqlx::query_scalar(
|
||||
"SELECT COUNT(*) FROM domains WHERE name = ? AND tld = ?"
|
||||
"SELECT COUNT(*) FROM domains WHERE name = $1 AND tld = $2"
|
||||
)
|
||||
.bind(&domain.name)
|
||||
.bind(&domain.tld)
|
||||
@@ -306,6 +306,56 @@ pub(crate) async fn delete_domain(ctx: &ServerContext, app_state: AppState, clai
|
||||
Ok(GurtResponse::ok().with_string_body("Domain deleted successfully"))
|
||||
}
|
||||
|
||||
pub(crate) async fn get_user_domains(ctx: &ServerContext, app_state: AppState, claims: Claims) -> Result<GurtResponse> {
|
||||
// Parse pagination from query parameters
|
||||
let path = ctx.path();
|
||||
let query_params = if let Some(query_start) = path.find('?') {
|
||||
let query_string = &path[query_start + 1..];
|
||||
parse_query_string(query_string)
|
||||
} else {
|
||||
HashMap::new()
|
||||
};
|
||||
|
||||
let page = query_params.get("page")
|
||||
.and_then(|p| p.parse::<u32>().ok())
|
||||
.unwrap_or(1)
|
||||
.max(1);
|
||||
|
||||
let page_size = query_params.get("limit")
|
||||
.and_then(|l| l.parse::<u32>().ok())
|
||||
.unwrap_or(100)
|
||||
.clamp(1, 1000);
|
||||
|
||||
let offset = (page - 1) * page_size;
|
||||
|
||||
let domains: Vec<Domain> = sqlx::query_as::<_, Domain>(
|
||||
"SELECT id, name, tld, ip, user_id, status, denial_reason, created_at FROM domains WHERE user_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3"
|
||||
)
|
||||
.bind(claims.user_id)
|
||||
.bind(page_size as i64)
|
||||
.bind(offset as i64)
|
||||
.fetch_all(&app_state.db)
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
let response_domains: Vec<UserDomain> = domains.into_iter().map(|domain| {
|
||||
UserDomain {
|
||||
name: domain.name,
|
||||
tld: domain.tld,
|
||||
ip: domain.ip,
|
||||
status: domain.status.unwrap_or_else(|| "pending".to_string()),
|
||||
denial_reason: domain.denial_reason,
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let response = UserDomainResponse {
|
||||
domains: response_domains,
|
||||
page,
|
||||
limit: page_size,
|
||||
};
|
||||
|
||||
Ok(GurtResponse::ok().with_json_body(&response)?)
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct Error {
|
||||
|
||||
Reference in New Issue
Block a user