security upgrade
This commit is contained in:
@@ -18,16 +18,33 @@ pub struct AccessTokenRequest {
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct AccessTokenResponse {
|
||||
access_token: String,
|
||||
granted: bool,
|
||||
expires_at: String,
|
||||
}
|
||||
|
||||
pub async fn create_resource_access_token(
|
||||
State(state): State<SharedState>,
|
||||
headers: HeaderMap,
|
||||
Json(payload): Json<AccessTokenRequest>,
|
||||
) -> Result<Json<AccessTokenResponse>, ApiError> {
|
||||
) -> Result<Response, ApiError> {
|
||||
let kind = payload.kind.trim();
|
||||
let slug = payload.slug.trim();
|
||||
let client_key = crate::security::client_key(&headers);
|
||||
let client_limit_key = format!("resource-password-client:{client_key}");
|
||||
let limit_key = format!("resource-password:{client_key}:{kind}:{slug}");
|
||||
let window = std::time::Duration::from_secs(15 * 60);
|
||||
state
|
||||
.check_rate_limit(client_limit_key, 50, window)
|
||||
.await
|
||||
.map_err(|seconds| ApiError::rate_limited(&format!(
|
||||
"Too many password attempts. Try again in {seconds} seconds."
|
||||
)))?;
|
||||
state
|
||||
.check_rate_limit(limit_key.clone(), 10, window)
|
||||
.await
|
||||
.map_err(|seconds| ApiError::rate_limited(&format!(
|
||||
"Too many password attempts. Try again in {seconds} seconds."
|
||||
)))?;
|
||||
match kind {
|
||||
"workspace" => {
|
||||
let workspace = db::find_workspace(&state.db, slug)
|
||||
@@ -63,10 +80,20 @@ pub async fn create_resource_access_token(
|
||||
.bind(&expires_at)
|
||||
.execute(state.db.pool())
|
||||
.await?;
|
||||
Ok(Json(AccessTokenResponse {
|
||||
access_token: token,
|
||||
state.clear_rate_limit(&limit_key).await;
|
||||
let cookie = crate::security::resource_cookie(
|
||||
kind,
|
||||
slug,
|
||||
&token,
|
||||
state.anonymous_access_token_ttl_days,
|
||||
);
|
||||
let mut response = Json(AccessTokenResponse {
|
||||
granted: true,
|
||||
expires_at,
|
||||
}))
|
||||
})
|
||||
.into_response();
|
||||
response.headers_mut().insert(header::SET_COOKIE, cookie);
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub async fn verify_resource_access_token(
|
||||
@@ -78,7 +105,7 @@ pub async fn verify_resource_access_token(
|
||||
let Some(token) = token.map(str::trim).filter(|value| !value.is_empty()) else {
|
||||
return Ok(false);
|
||||
};
|
||||
if crate::auth::resource_permission(state, kind, slug, Some(token))
|
||||
if crate::auth::share_link_permission(state, kind, slug, Some(token))
|
||||
.await
|
||||
.map_err(|error| ApiError::forbidden(&error.message))?
|
||||
.is_some()
|
||||
|
||||
Reference in New Issue
Block a user