62 lines
1.7 KiB
Rust
62 lines
1.7 KiB
Rust
#[derive(Debug, Deserialize)]
|
|
struct CreateAccessTokenRequest {
|
|
name: Option<String>,
|
|
}
|
|
|
|
async fn list_access_tokens(
|
|
State(state): State<AppState>,
|
|
) -> Result<Json<Vec<ApiTokenInfo>>, AppError> {
|
|
Ok(Json(state.db.list_api_tokens()?))
|
|
}
|
|
|
|
async fn create_access_token(
|
|
State(state): State<AppState>,
|
|
Json(input): Json<CreateAccessTokenRequest>,
|
|
) -> Result<(StatusCode, Json<Value>), AppError> {
|
|
let name = input
|
|
.name
|
|
.unwrap_or_else(|| "Home Assistant".into())
|
|
.trim()
|
|
.to_string();
|
|
if name.is_empty() || name.len() > 80 {
|
|
return Err(AppError::BadRequest(
|
|
"token name must contain 1 to 80 characters".into(),
|
|
));
|
|
}
|
|
|
|
let secret = generate_access_token();
|
|
let item = ApiTokenInfo {
|
|
id: Uuid::new_v4().to_string(),
|
|
name,
|
|
token_prefix: format!("{}...", secret.chars().take(24).collect::<String>()),
|
|
created_at: Utc::now(),
|
|
};
|
|
state.db.save_api_token(&item, &hash_token(&secret))?;
|
|
state.log(
|
|
"info",
|
|
"access_token.created",
|
|
"Created a Home Assistant access token",
|
|
json!({"token_id": item.id.clone(), "name": item.name.clone()}),
|
|
);
|
|
Ok((
|
|
StatusCode::CREATED,
|
|
Json(json!({"token": secret, "item": item})),
|
|
))
|
|
}
|
|
|
|
async fn delete_access_token(
|
|
State(state): State<AppState>,
|
|
Path(id): Path<String>,
|
|
) -> Result<StatusCode, AppError> {
|
|
if !state.db.delete_api_token(&id)? {
|
|
return Err(AppError::NotFound(format!("access token {id}")));
|
|
}
|
|
state.log(
|
|
"info",
|
|
"access_token.revoked",
|
|
"Revoked a Home Assistant access token",
|
|
json!({"token_id": id}),
|
|
);
|
|
Ok(StatusCode::NO_CONTENT)
|
|
}
|