first commit
This commit is contained in:
commit
2eb8aac027
91 files changed
+20139
No files matched your search
@@ -0,0 +1,106 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
Json,
|
||||
extract::{Path, State},
|
||||
http::HeaderMap,
|
||||
};
|
||||
use axum_extra::extract::cookie::CookieJar;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
db::{Table, row_string},
|
||||
error::{AppError, AppResult},
|
||||
routes,
|
||||
state::AppState,
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Preference {
|
||||
pub key: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct PreferenceInput {
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
pub async fn list(
|
||||
State(state): State<Arc<AppState>>,
|
||||
jar: CookieJar,
|
||||
) -> AppResult<Json<Vec<Preference>>> {
|
||||
let session = routes::session(&state, &jar)?;
|
||||
session.require_admin()?;
|
||||
if !state.db.has_table(Table::AdminPreferences).await {
|
||||
return Ok(Json(Vec::new()));
|
||||
}
|
||||
let table = state.db.table(Table::AdminPreferences);
|
||||
let sql = state.db.q(&format!(
|
||||
"SELECT pref_key,pref_value FROM {table} WHERE username=? ORDER BY pref_key"
|
||||
));
|
||||
let rows = sqlx::query(&sql)
|
||||
.bind(&session.username)
|
||||
.fetch_all(state.db.pool())
|
||||
.await?;
|
||||
Ok(Json(
|
||||
rows.iter()
|
||||
.map(|row| Preference {
|
||||
key: row_string(row, "pref_key"),
|
||||
value: row_string(row, "pref_value"),
|
||||
})
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn set(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Path(key): Path<String>,
|
||||
jar: CookieJar,
|
||||
headers: HeaderMap,
|
||||
Json(input): Json<PreferenceInput>,
|
||||
) -> AppResult<Json<serde_json::Value>> {
|
||||
let session = routes::mutation_session(&state, &jar, &headers)?;
|
||||
session.require_admin()?;
|
||||
validate_key(&key)?;
|
||||
if input.value.len() > 2048 {
|
||||
return Err(AppError::bad_request("Preference value is too long"));
|
||||
}
|
||||
if !state.db.has_table(Table::AdminPreferences).await {
|
||||
return Err(AppError::conflict(
|
||||
"admin_preferences table is not available",
|
||||
));
|
||||
}
|
||||
state
|
||||
.db
|
||||
.set_admin_pref(&session.username, &key, &input.value)
|
||||
.await?;
|
||||
Ok(Json(serde_json::json!({"ok": true})))
|
||||
}
|
||||
|
||||
pub async fn remove(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Path(key): Path<String>,
|
||||
jar: CookieJar,
|
||||
headers: HeaderMap,
|
||||
) -> AppResult<Json<serde_json::Value>> {
|
||||
let session = routes::mutation_session(&state, &jar, &headers)?;
|
||||
session.require_admin()?;
|
||||
validate_key(&key)?;
|
||||
if state.db.has_table(Table::AdminPreferences).await {
|
||||
state.db.delete_admin_pref(&session.username, &key).await?;
|
||||
}
|
||||
Ok(Json(serde_json::json!({"ok": true})))
|
||||
}
|
||||
|
||||
fn validate_key(key: &str) -> AppResult<()> {
|
||||
if key.is_empty()
|
||||
|| key.len() > 64
|
||||
|| !key
|
||||
.bytes()
|
||||
.all(|b| b.is_ascii_alphanumeric() || matches!(b, b'_' | b'-' | b'.'))
|
||||
{
|
||||
return Err(AppError::bad_request("Invalid preference key"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user