chore: checkpoint turso and ai runtime work
This commit is contained in:
@@ -658,7 +658,7 @@ pub(crate) fn ensure_local_workspace_access_with_state(
|
||||
}
|
||||
let actor_id = context.auth.actor_id.trim();
|
||||
let canonical_root_uri = file_uri_for_path(&canonical_root);
|
||||
let sqlite_access = state
|
||||
let control_plane_access = state
|
||||
.control_plane()
|
||||
.resolve_access(actor_id, &canonical_root_uri)
|
||||
.unwrap_or_else(|error| {
|
||||
@@ -675,7 +675,7 @@ pub(crate) fn ensure_local_workspace_access_with_state(
|
||||
grant_ids: Vec::new(),
|
||||
}
|
||||
});
|
||||
if local_access_permission_allows(&sqlite_access.permission, mode) {
|
||||
if local_access_permission_allows(&control_plane_access.permission, mode) {
|
||||
return Ok(canonical_root);
|
||||
}
|
||||
ensure_local_workspace_access_for_actor_with_mode(
|
||||
@@ -785,22 +785,8 @@ pub(crate) fn control_plane_status_display() -> String {
|
||||
.ok()
|
||||
.map(|value| value.trim().to_string())
|
||||
.filter(|value| !value.is_empty())
|
||||
.unwrap_or_else(|| "sqlite".to_string());
|
||||
.unwrap_or_else(|| "libsql-local".to_string());
|
||||
match backend.as_str() {
|
||||
"sqlite" => {
|
||||
let db_path = std::env::var("MNOTE_CONTROL_PLANE_DB_PATH")
|
||||
.ok()
|
||||
.map(|value| value.trim().to_string())
|
||||
.filter(|value| !value.is_empty())
|
||||
.unwrap_or_else(|| {
|
||||
default_local_workspace_base_dir()
|
||||
.join("control-plane")
|
||||
.join("control-plane.db")
|
||||
.display()
|
||||
.to_string()
|
||||
});
|
||||
format!("backend=sqlite; db={db_path}")
|
||||
}
|
||||
"libsql-local" | "turso-local" | "turso" => {
|
||||
let db_path = std::env::var("MNOTE_TURSO_LOCAL_PATH")
|
||||
.ok()
|
||||
@@ -850,6 +836,7 @@ pub(crate) fn control_plane_status_display() -> String {
|
||||
});
|
||||
format!("backend=turso-synced; local={db_path}; remote=env:MNOTE_TURSO_DATABASE_URL")
|
||||
}
|
||||
"sqlite" => "backend=sqlite; unsupported-runtime; use control-plane-admin only".to_string(),
|
||||
other => format!("backend={other}; unsupported"),
|
||||
}
|
||||
}
|
||||
@@ -1211,7 +1198,7 @@ fn append_control_plane_outbox_event(state: &AppState, event_type: &str, payload
|
||||
let _ = state.stream_delta_tx.send(delta);
|
||||
}
|
||||
|
||||
fn list_sqlite_share_links_for_context(
|
||||
fn list_control_plane_share_links_for_context(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
query: ShareLinkListQuery,
|
||||
@@ -1227,15 +1214,15 @@ fn list_sqlite_share_links_for_context(
|
||||
let links = state
|
||||
.control_plane()
|
||||
.list_share_links(workspace_id)
|
||||
.map_err(|error| WebError::internal(format!("SQLite 分享链接读取失败: {error}")))?;
|
||||
.map_err(|error| WebError::internal(format!("control-plane 分享链接读取失败: {error}")))?;
|
||||
Ok(json!({
|
||||
"ok": true,
|
||||
"controlPlane": "sqlite",
|
||||
"controlPlane": "control-plane",
|
||||
"links": links.iter().map(share_link_payload).collect::<Vec<_>>(),
|
||||
}))
|
||||
}
|
||||
|
||||
fn create_sqlite_share_link_for_context(
|
||||
fn create_control_plane_share_link_for_context(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
request: LocalShareLinkRequest,
|
||||
@@ -1263,7 +1250,7 @@ fn create_sqlite_share_link_for_context(
|
||||
created_by: context.auth.actor_id.trim().to_string(),
|
||||
expires_at: request.expires_at,
|
||||
})
|
||||
.map_err(|error| WebError::internal(format!("SQLite 分享链接写入失败: {error}")))?;
|
||||
.map_err(|error| WebError::internal(format!("control-plane 分享链接写入失败: {error}")))?;
|
||||
let _ = state.control_plane().append_audit(AppendAuditInput {
|
||||
actor_user_id: Some(context.auth.actor_id.trim().to_string()),
|
||||
action: "control.share.created".to_string(),
|
||||
@@ -1286,13 +1273,13 @@ fn create_sqlite_share_link_for_context(
|
||||
);
|
||||
Ok(json!({
|
||||
"ok": true,
|
||||
"controlPlane": "sqlite",
|
||||
"controlPlane": "control-plane",
|
||||
"token": created.token,
|
||||
"link": share_link_payload(&created.link),
|
||||
}))
|
||||
}
|
||||
|
||||
fn revoke_sqlite_share_link_for_context(
|
||||
fn revoke_control_plane_share_link_for_context(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
link_id: &str,
|
||||
@@ -1312,7 +1299,7 @@ fn revoke_sqlite_share_link_for_context(
|
||||
control_plane::ControlPlaneError::NotFound(message) => {
|
||||
WebError::new(StatusCode::NOT_FOUND, "share_link_not_found", message)
|
||||
}
|
||||
other => WebError::internal(format!("SQLite 分享链接撤销失败: {other}")),
|
||||
other => WebError::internal(format!("control-plane 分享链接撤销失败: {other}")),
|
||||
})?;
|
||||
let _ = state.control_plane().append_audit(AppendAuditInput {
|
||||
actor_user_id: Some(context.auth.actor_id.trim().to_string()),
|
||||
@@ -1330,7 +1317,7 @@ fn revoke_sqlite_share_link_for_context(
|
||||
);
|
||||
Ok(json!({
|
||||
"ok": true,
|
||||
"controlPlane": "sqlite",
|
||||
"controlPlane": "control-plane",
|
||||
"revokedLinkId": link_id,
|
||||
}))
|
||||
}
|
||||
@@ -1879,7 +1866,7 @@ fn is_default_workspace_auto_grant(grant: &DirectoryGrantRecord) -> bool {
|
||||
&& grant.root_uri.ends_with("/workspaces/my-space")
|
||||
}
|
||||
|
||||
fn sqlite_access_policy_payload(
|
||||
fn control_plane_access_policy_payload(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
) -> Result<Value, WebError> {
|
||||
@@ -1887,14 +1874,14 @@ fn sqlite_access_policy_payload(
|
||||
let grants = state
|
||||
.control_plane()
|
||||
.list_directory_grants()
|
||||
.map_err(|error| WebError::internal(format!("SQLite 控制面授权列表读取失败: {error}")))?;
|
||||
.map_err(|error| WebError::internal(format!("control-plane授权列表读取失败: {error}")))?;
|
||||
let grant_values = grants
|
||||
.iter()
|
||||
.map(control_plane_grant_payload)
|
||||
.collect::<Vec<_>>();
|
||||
Ok(json!({
|
||||
"ok": true,
|
||||
"controlPlane": "sqlite",
|
||||
"controlPlane": "control-plane",
|
||||
"policyPath": local_access_policy_path().display().to_string(),
|
||||
"policy": {
|
||||
"admins": policy.admins,
|
||||
@@ -1907,7 +1894,7 @@ fn sqlite_access_policy_payload(
|
||||
}))
|
||||
}
|
||||
|
||||
fn sqlite_user_access_policy_payload(
|
||||
fn control_plane_user_access_policy_payload(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
) -> Result<Value, WebError> {
|
||||
@@ -1922,7 +1909,7 @@ fn sqlite_user_access_policy_payload(
|
||||
let grants = state
|
||||
.control_plane()
|
||||
.list_directory_grants()
|
||||
.map_err(|error| WebError::internal(format!("SQLite 控制面授权列表读取失败: {error}")))?;
|
||||
.map_err(|error| WebError::internal(format!("control-plane授权列表读取失败: {error}")))?;
|
||||
let grant_values = grants
|
||||
.iter()
|
||||
.filter(|grant| {
|
||||
@@ -1933,7 +1920,7 @@ fn sqlite_user_access_policy_payload(
|
||||
.collect::<Vec<_>>();
|
||||
Ok(json!({
|
||||
"ok": true,
|
||||
"controlPlane": "sqlite",
|
||||
"controlPlane": "control-plane",
|
||||
"policy": {
|
||||
"grants": grant_values,
|
||||
},
|
||||
@@ -1956,7 +1943,7 @@ fn validate_local_access_root_for_context(
|
||||
}))
|
||||
}
|
||||
|
||||
fn add_sqlite_user_access_grant_for_context(
|
||||
fn add_control_plane_user_access_grant_for_context(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
mut request: LocalAccessGrantRequest,
|
||||
@@ -1973,19 +1960,19 @@ fn add_sqlite_user_access_grant_for_context(
|
||||
ensure_path_inside_owned_local_workspace(actor_id, &canonical)?;
|
||||
request.root_uri = file_uri_for_path(&canonical);
|
||||
request.root_path = canonical.display().to_string();
|
||||
add_sqlite_local_access_grant_for_context_inner(state, context, request, "user")
|
||||
add_control_plane_local_access_grant_for_context_inner(state, context, request, "user")
|
||||
}
|
||||
|
||||
fn add_sqlite_local_access_grant_for_context(
|
||||
fn add_control_plane_local_access_grant_for_context(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
request: LocalAccessGrantRequest,
|
||||
) -> Result<Value, WebError> {
|
||||
let _policy = require_local_access_policy_admin(context)?;
|
||||
add_sqlite_local_access_grant_for_context_inner(state, context, request, "admin")
|
||||
add_control_plane_local_access_grant_for_context_inner(state, context, request, "admin")
|
||||
}
|
||||
|
||||
fn add_sqlite_local_access_grant_for_context_inner(
|
||||
fn add_control_plane_local_access_grant_for_context_inner(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
request: LocalAccessGrantRequest,
|
||||
@@ -2010,7 +1997,7 @@ fn add_sqlite_local_access_grant_for_context_inner(
|
||||
root_uri: Some(root_uri.clone()),
|
||||
include_revoked: false,
|
||||
})
|
||||
.map_err(|error| WebError::internal(format!("SQLite 控制面授权查重失败: {error}")))?;
|
||||
.map_err(|error| WebError::internal(format!("control-plane授权查重失败: {error}")))?;
|
||||
if duplicates.iter().any(|grant| {
|
||||
grant.permission.trim() == permission
|
||||
&& grant.recursive == request.recursive
|
||||
@@ -2035,7 +2022,7 @@ fn add_sqlite_local_access_grant_for_context_inner(
|
||||
source: source.to_string(),
|
||||
created_by: Some(context.auth.actor_id.trim().to_string()),
|
||||
})
|
||||
.map_err(|error| WebError::internal(format!("SQLite 控制面授权写入失败: {error}")))?;
|
||||
.map_err(|error| WebError::internal(format!("control-plane授权写入失败: {error}")))?;
|
||||
let _ = state.control_plane().append_audit(AppendAuditInput {
|
||||
actor_user_id: Some(context.auth.actor_id.trim().to_string()),
|
||||
action: "control.grant.created".to_string(),
|
||||
@@ -2058,14 +2045,14 @@ fn add_sqlite_local_access_grant_for_context_inner(
|
||||
let grants = state
|
||||
.control_plane()
|
||||
.list_directory_grants()
|
||||
.map_err(|error| WebError::internal(format!("SQLite 控制面授权列表读取失败: {error}")))?;
|
||||
.map_err(|error| WebError::internal(format!("control-plane授权列表读取失败: {error}")))?;
|
||||
let grant_values = grants
|
||||
.iter()
|
||||
.map(control_plane_grant_payload)
|
||||
.collect::<Vec<_>>();
|
||||
Ok(json!({
|
||||
"ok": true,
|
||||
"controlPlane": "sqlite",
|
||||
"controlPlane": "control-plane",
|
||||
"policyPath": local_access_policy_path().display().to_string(),
|
||||
"grant": control_plane_grant_payload(&grant),
|
||||
"policy": {
|
||||
@@ -2074,7 +2061,7 @@ fn add_sqlite_local_access_grant_for_context_inner(
|
||||
}))
|
||||
}
|
||||
|
||||
fn delete_sqlite_user_access_grant_for_context(
|
||||
fn delete_control_plane_user_access_grant_for_context(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
grant_id: &str,
|
||||
@@ -2102,7 +2089,7 @@ fn delete_sqlite_user_access_grant_for_context(
|
||||
root_uri: None,
|
||||
include_revoked: false,
|
||||
})
|
||||
.map_err(|error| WebError::internal(format!("SQLite 控制面授权查找失败: {error}")))?;
|
||||
.map_err(|error| WebError::internal(format!("control-plane授权查找失败: {error}")))?;
|
||||
let grant = grants.first().ok_or_else(|| {
|
||||
WebError::new(
|
||||
StatusCode::NOT_FOUND,
|
||||
@@ -2134,7 +2121,7 @@ fn delete_sqlite_user_access_grant_for_context(
|
||||
"local_access_policy_grant_not_found",
|
||||
message,
|
||||
),
|
||||
other => WebError::internal(format!("SQLite 控制面授权撤销失败: {other}")),
|
||||
other => WebError::internal(format!("control-plane授权撤销失败: {other}")),
|
||||
})?;
|
||||
let _ = state.control_plane().append_audit(AppendAuditInput {
|
||||
actor_user_id: Some(actor_id.to_string()),
|
||||
@@ -2152,14 +2139,14 @@ fn delete_sqlite_user_access_grant_for_context(
|
||||
);
|
||||
Ok(json!({
|
||||
"ok": true,
|
||||
"controlPlane": "sqlite",
|
||||
"controlPlane": "control-plane",
|
||||
"deletedGrantId": grant_id,
|
||||
"revokedUserId": revoked_user_id,
|
||||
"policy": {
|
||||
"grants": state
|
||||
.control_plane()
|
||||
.list_directory_grants()
|
||||
.map_err(|error| WebError::internal(format!("SQLite 控制面授权列表读取失败: {error}")))?
|
||||
.map_err(|error| WebError::internal(format!("control-plane授权列表读取失败: {error}")))?
|
||||
.iter()
|
||||
.filter(|grant| grant.created_by.as_deref().map(str::trim) == Some(actor_id))
|
||||
.map(control_plane_grant_payload)
|
||||
@@ -2168,7 +2155,7 @@ fn delete_sqlite_user_access_grant_for_context(
|
||||
}))
|
||||
}
|
||||
|
||||
fn delete_sqlite_local_access_grant_for_context(
|
||||
fn delete_control_plane_local_access_grant_for_context(
|
||||
state: &AppState,
|
||||
context: &RequestContext,
|
||||
grant_id: &str,
|
||||
@@ -2189,7 +2176,7 @@ fn delete_sqlite_local_access_grant_for_context(
|
||||
root_uri: None,
|
||||
include_revoked: false,
|
||||
})
|
||||
.map_err(|error| WebError::internal(format!("SQLite 控制面授权查找失败: {error}")))?;
|
||||
.map_err(|error| WebError::internal(format!("control-plane授权查找失败: {error}")))?;
|
||||
if grants
|
||||
.first()
|
||||
.map(is_default_workspace_auto_grant)
|
||||
@@ -2211,7 +2198,7 @@ fn delete_sqlite_local_access_grant_for_context(
|
||||
"local_access_policy_grant_not_found",
|
||||
message,
|
||||
),
|
||||
other => WebError::internal(format!("SQLite 控制面授权撤销失败: {other}")),
|
||||
other => WebError::internal(format!("control-plane授权撤销失败: {other}")),
|
||||
})?;
|
||||
let _ = state.control_plane().append_audit(AppendAuditInput {
|
||||
actor_user_id: Some(context.auth.actor_id.trim().to_string()),
|
||||
@@ -2229,7 +2216,7 @@ fn delete_sqlite_local_access_grant_for_context(
|
||||
);
|
||||
Ok(json!({
|
||||
"ok": true,
|
||||
"controlPlane": "sqlite",
|
||||
"controlPlane": "control-plane",
|
||||
"policyPath": local_access_policy_path().display().to_string(),
|
||||
"deletedGrantId": grant_id,
|
||||
"revokedUserId": revoked_user_id,
|
||||
@@ -2237,7 +2224,7 @@ fn delete_sqlite_local_access_grant_for_context(
|
||||
"grants": state
|
||||
.control_plane()
|
||||
.list_directory_grants()
|
||||
.map_err(|error| WebError::internal(format!("SQLite 控制面授权列表读取失败: {error}")))?
|
||||
.map_err(|error| WebError::internal(format!("control-plane授权列表读取失败: {error}")))?
|
||||
.iter()
|
||||
.map(control_plane_grant_payload)
|
||||
.collect::<Vec<_>>(),
|
||||
@@ -2420,7 +2407,7 @@ pub async fn get_local_access_policy(
|
||||
State(state): State<AppState>,
|
||||
Extension(context): Extension<RequestContext>,
|
||||
) -> Result<(StatusCode, Json<Value>), WebError> {
|
||||
let payload = sqlite_access_policy_payload(&state, &context)
|
||||
let payload = control_plane_access_policy_payload(&state, &context)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
Ok((StatusCode::OK, Json(payload)))
|
||||
}
|
||||
@@ -2429,7 +2416,7 @@ pub async fn get_user_access_policy(
|
||||
State(state): State<AppState>,
|
||||
Extension(context): Extension<RequestContext>,
|
||||
) -> Result<(StatusCode, Json<Value>), WebError> {
|
||||
let payload = sqlite_user_access_policy_payload(&state, &context)
|
||||
let payload = control_plane_user_access_policy_payload(&state, &context)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
Ok((StatusCode::OK, Json(payload)))
|
||||
}
|
||||
@@ -2448,7 +2435,7 @@ pub async fn create_local_access_grant(
|
||||
Extension(context): Extension<RequestContext>,
|
||||
Json(request): Json<LocalAccessGrantRequest>,
|
||||
) -> Result<(StatusCode, Json<Value>), WebError> {
|
||||
let payload = add_sqlite_local_access_grant_for_context(&state, &context, request)
|
||||
let payload = add_control_plane_local_access_grant_for_context(&state, &context, request)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
if let Some(user_id) = payload
|
||||
.pointer("/grant/userId")
|
||||
@@ -2466,7 +2453,7 @@ pub async fn create_user_access_grant(
|
||||
Extension(context): Extension<RequestContext>,
|
||||
Json(request): Json<LocalAccessGrantRequest>,
|
||||
) -> Result<(StatusCode, Json<Value>), WebError> {
|
||||
let payload = add_sqlite_user_access_grant_for_context(&state, &context, request)
|
||||
let payload = add_control_plane_user_access_grant_for_context(&state, &context, request)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
if let Some(user_id) = payload
|
||||
.pointer("/grant/userId")
|
||||
@@ -2484,7 +2471,7 @@ pub async fn delete_local_access_grant(
|
||||
Extension(context): Extension<RequestContext>,
|
||||
AxumPath(grant_id): AxumPath<String>,
|
||||
) -> Result<(StatusCode, Json<Value>), WebError> {
|
||||
let payload = delete_sqlite_local_access_grant_for_context(&state, &context, &grant_id)
|
||||
let payload = delete_control_plane_local_access_grant_for_context(&state, &context, &grant_id)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
if let Some(user_id) = payload
|
||||
.get("revokedUserId")
|
||||
@@ -2502,7 +2489,7 @@ pub async fn delete_user_access_grant(
|
||||
Extension(context): Extension<RequestContext>,
|
||||
AxumPath(grant_id): AxumPath<String>,
|
||||
) -> Result<(StatusCode, Json<Value>), WebError> {
|
||||
let payload = delete_sqlite_user_access_grant_for_context(&state, &context, &grant_id)
|
||||
let payload = delete_control_plane_user_access_grant_for_context(&state, &context, &grant_id)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
if let Some(user_id) = payload
|
||||
.get("revokedUserId")
|
||||
@@ -2536,7 +2523,7 @@ pub async fn get_share_links(
|
||||
Extension(context): Extension<RequestContext>,
|
||||
Query(query): Query<ShareLinkListQuery>,
|
||||
) -> Result<(StatusCode, Json<Value>), WebError> {
|
||||
let payload = list_sqlite_share_links_for_context(&state, &context, query)
|
||||
let payload = list_control_plane_share_links_for_context(&state, &context, query)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
Ok((StatusCode::OK, Json(payload)))
|
||||
}
|
||||
@@ -2546,7 +2533,7 @@ pub async fn create_share_link(
|
||||
Extension(context): Extension<RequestContext>,
|
||||
Json(request): Json<LocalShareLinkRequest>,
|
||||
) -> Result<(StatusCode, Json<Value>), WebError> {
|
||||
let payload = create_sqlite_share_link_for_context(&state, &context, request)
|
||||
let payload = create_control_plane_share_link_for_context(&state, &context, request)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
Ok((StatusCode::OK, Json(payload)))
|
||||
}
|
||||
@@ -2556,7 +2543,7 @@ pub async fn delete_share_link(
|
||||
Extension(context): Extension<RequestContext>,
|
||||
AxumPath(link_id): AxumPath<String>,
|
||||
) -> Result<(StatusCode, Json<Value>), WebError> {
|
||||
let payload = revoke_sqlite_share_link_for_context(&state, &context, &link_id)
|
||||
let payload = revoke_control_plane_share_link_for_context(&state, &context, &link_id)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
Ok((StatusCode::OK, Json(payload)))
|
||||
}
|
||||
@@ -9578,7 +9565,7 @@ fn markdown_page_subtree(document_id: &str, title: &str, content: &Value) -> Val
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
add_sqlite_local_access_grant_for_context,
|
||||
add_control_plane_local_access_grant_for_context,
|
||||
create_default_local_workspace_for_actor_at_base, create_local_access_grant,
|
||||
create_share_grant, create_share_link, create_user_access_grant, create_user_share_grant,
|
||||
delete_share_link, delete_user_access_grant, editor_blocks_to_markdown_for_file,
|
||||
@@ -11054,7 +11041,7 @@ fn main() {}
|
||||
.expect("created grant id")
|
||||
.to_string();
|
||||
assert_eq!(created["grant"]["permission"], "read");
|
||||
assert_eq!(created["controlPlane"], "sqlite");
|
||||
assert_eq!(created["controlPlane"], "control-plane");
|
||||
let created_events = state
|
||||
.control_plane()
|
||||
.drain_outbox(10)
|
||||
@@ -11080,7 +11067,7 @@ fn main() {}
|
||||
.expect_err("created read grant cannot write");
|
||||
assert_eq!(write_error.status(), StatusCode::FORBIDDEN);
|
||||
|
||||
let duplicate_error = add_sqlite_local_access_grant_for_context(
|
||||
let duplicate_error = add_control_plane_local_access_grant_for_context(
|
||||
&state,
|
||||
&request_context("admin_1", "user"),
|
||||
LocalAccessGrantRequest {
|
||||
@@ -11262,7 +11249,7 @@ fn main() {}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_access_policy_grant_uses_sqlite_directory_grants_for_owned_folder() {
|
||||
async fn user_access_policy_grant_uses_control_plane_directory_grants_for_owned_folder() {
|
||||
let _guard = env_lock().lock().expect("env lock");
|
||||
let owned_root = temp_root("mnote-user-access-policy-owned-root");
|
||||
let outside_root = temp_root("mnote-user-access-policy-outside-root");
|
||||
@@ -11304,7 +11291,7 @@ fn main() {}
|
||||
.as_str()
|
||||
.expect("grant id")
|
||||
.to_string();
|
||||
assert_eq!(created["controlPlane"], "sqlite");
|
||||
assert_eq!(created["controlPlane"], "control-plane");
|
||||
assert_eq!(created["grant"]["userId"], "user_target");
|
||||
assert_eq!(created["grant"]["createdBy"], "user_owner");
|
||||
assert_eq!(created["grant"]["permission"], "write");
|
||||
@@ -11324,7 +11311,7 @@ fn main() {}
|
||||
)
|
||||
.await
|
||||
.expect("owner can list self-created directory grants");
|
||||
assert_eq!(listed["controlPlane"], "sqlite");
|
||||
assert_eq!(listed["controlPlane"], "control-plane");
|
||||
assert_eq!(listed["grants"][0]["id"], grant_id);
|
||||
assert_eq!(listed["grants"][0]["permission"], "write");
|
||||
|
||||
@@ -11334,7 +11321,7 @@ fn main() {}
|
||||
)
|
||||
.await
|
||||
.expect("target can list incoming directory grants");
|
||||
assert_eq!(target_listed["controlPlane"], "sqlite");
|
||||
assert_eq!(target_listed["controlPlane"], "control-plane");
|
||||
assert_eq!(target_listed["grants"][0]["id"], grant_id);
|
||||
assert_eq!(target_listed["grants"][0]["userId"], "user_target");
|
||||
|
||||
@@ -11452,7 +11439,7 @@ fn main() {}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn share_link_api_creates_lists_and_revokes_sqlite_record() {
|
||||
async fn share_link_api_creates_lists_and_revokes_control_plane_record() {
|
||||
let _guard = env_lock().lock().expect("env lock");
|
||||
let state = test_state();
|
||||
std::env::set_var("MNOTE_ADMIN_USER_IDS", "admin_1");
|
||||
@@ -11488,7 +11475,7 @@ fn main() {}
|
||||
.await
|
||||
.expect("admin can create share link");
|
||||
let link_id = created["link"]["id"].as_str().expect("link id").to_string();
|
||||
assert_eq!(created["controlPlane"], "sqlite");
|
||||
assert_eq!(created["controlPlane"], "control-plane");
|
||||
assert_eq!(created["token"], "visible-token");
|
||||
assert!(created["link"].get("tokenHash").is_none());
|
||||
assert_eq!(created["link"]["permission"], "read");
|
||||
@@ -11507,7 +11494,7 @@ fn main() {}
|
||||
let stored = state
|
||||
.control_plane()
|
||||
.list_share_links(&workspace.id)
|
||||
.expect("list sqlite share links");
|
||||
.expect("list control-plane share links");
|
||||
assert_eq!(stored.len(), 1);
|
||||
assert_eq!(stored[0].id, link_id);
|
||||
assert_ne!(stored[0].token_hash, "visible-token");
|
||||
@@ -12691,30 +12678,30 @@ fn main() {}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn local_file_open_allows_sqlite_directory_read_grant_without_json_policy() {
|
||||
async fn local_file_open_allows_control_plane_directory_read_grant_without_json_policy() {
|
||||
let _guard = env_lock().lock().expect("env lock");
|
||||
let root = temp_root("mnote-local-file-open-sqlite-read-grant-root");
|
||||
let policy_root = temp_root("mnote-local-file-open-sqlite-read-grant-config");
|
||||
let root = temp_root("mnote-local-file-open-control-plane-read-grant-root");
|
||||
let policy_root = temp_root("mnote-local-file-open-control-plane-read-grant-config");
|
||||
let policy_file = policy_root.join("missing-access-policy.json");
|
||||
let state = test_state();
|
||||
let root_uri = format!("file://{}", root.display());
|
||||
std::fs::write(root.join("README.txt"), "hello sqlite").expect("write file");
|
||||
std::fs::write(root.join("README.txt"), "hello control plane").expect("write file");
|
||||
std::env::set_var("MNOTE_LOCAL_ACCESS_POLICY_FILE", &policy_file);
|
||||
state
|
||||
.control_plane()
|
||||
.upsert_user(UpsertUserInput {
|
||||
id: Some("sqlite_reader".into()),
|
||||
email: Some("sqlite-reader@example.com".into()),
|
||||
username: "sqlite_reader".into(),
|
||||
display_name: "sqlite_reader".into(),
|
||||
id: Some("control_plane_reader".into()),
|
||||
email: Some("control-plane-reader@example.com".into()),
|
||||
username: "control_plane_reader".into(),
|
||||
display_name: "control_plane_reader".into(),
|
||||
role: None,
|
||||
password_hash: None,
|
||||
})
|
||||
.expect("upsert sqlite reader");
|
||||
.expect("upsert control-plane reader");
|
||||
state
|
||||
.control_plane()
|
||||
.grant_directory_access(DirectoryGrantInput {
|
||||
user_id: "sqlite_reader".into(),
|
||||
user_id: "control_plane_reader".into(),
|
||||
workspace_id: None,
|
||||
root_uri: root_uri.clone(),
|
||||
root_path: root
|
||||
@@ -12728,9 +12715,9 @@ fn main() {}
|
||||
source: "test".into(),
|
||||
created_by: None,
|
||||
})
|
||||
.expect("grant sqlite read");
|
||||
.expect("grant control-plane read");
|
||||
|
||||
let context = request_context("sqlite_reader", "user");
|
||||
let context = request_context("control_plane_reader", "user");
|
||||
let (_, _, bytes) = open_local_file(
|
||||
State(state),
|
||||
Extension(context),
|
||||
@@ -12741,8 +12728,8 @@ fn main() {}
|
||||
}),
|
||||
)
|
||||
.await
|
||||
.expect("sqlite read grant can open local file");
|
||||
assert_eq!(bytes, b"hello sqlite");
|
||||
.expect("control-plane read grant can open local file");
|
||||
assert_eq!(bytes, b"hello control plane");
|
||||
assert!(!policy_file.exists(), "SQLite grant 不应写旧 JSON policy");
|
||||
|
||||
std::env::remove_var("MNOTE_LOCAL_ACCESS_POLICY_FILE");
|
||||
@@ -12751,32 +12738,32 @@ fn main() {}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn local_file_open_allows_legacy_sqlite_directory_grant_with_path_root_uri() {
|
||||
async fn local_file_open_allows_legacy_control_plane_directory_grant_with_path_root_uri() {
|
||||
let _guard = env_lock().lock().expect("env lock");
|
||||
let root = temp_root("mnote-local-file-open-legacy-sqlite-grant-root");
|
||||
let policy_root = temp_root("mnote-local-file-open-legacy-sqlite-grant-config");
|
||||
let root = temp_root("mnote-local-file-open-legacy-control-plane-grant-root");
|
||||
let policy_root = temp_root("mnote-local-file-open-legacy-control-plane-grant-config");
|
||||
let policy_file = policy_root.join("missing-access-policy.json");
|
||||
let state = test_state();
|
||||
let canonical_root = root.canonicalize().expect("canonical root");
|
||||
let canonical_root_path = canonical_root.display().to_string();
|
||||
let root_uri = format!("file://{canonical_root_path}");
|
||||
std::fs::write(root.join("README.txt"), "hello legacy sqlite").expect("write file");
|
||||
std::fs::write(root.join("README.txt"), "hello legacy control plane").expect("write file");
|
||||
std::env::set_var("MNOTE_LOCAL_ACCESS_POLICY_FILE", &policy_file);
|
||||
state
|
||||
.control_plane()
|
||||
.upsert_user(UpsertUserInput {
|
||||
id: Some("legacy_sqlite_reader".into()),
|
||||
email: Some("legacy-sqlite-reader@example.com".into()),
|
||||
username: "legacy_sqlite_reader".into(),
|
||||
display_name: "legacy_sqlite_reader".into(),
|
||||
id: Some("legacy_control_plane_reader".into()),
|
||||
email: Some("legacy-control-plane-reader@example.com".into()),
|
||||
username: "legacy_control_plane_reader".into(),
|
||||
display_name: "legacy_control_plane_reader".into(),
|
||||
role: None,
|
||||
password_hash: None,
|
||||
})
|
||||
.expect("upsert sqlite reader");
|
||||
.expect("upsert control-plane reader");
|
||||
state
|
||||
.control_plane()
|
||||
.grant_directory_access(DirectoryGrantInput {
|
||||
user_id: "legacy_sqlite_reader".into(),
|
||||
user_id: "legacy_control_plane_reader".into(),
|
||||
workspace_id: None,
|
||||
root_uri: canonical_root_path.clone(),
|
||||
root_path: canonical_root_path,
|
||||
@@ -12786,9 +12773,9 @@ fn main() {}
|
||||
source: "legacy-test".into(),
|
||||
created_by: None,
|
||||
})
|
||||
.expect("grant legacy sqlite read");
|
||||
.expect("grant legacy control-plane read");
|
||||
|
||||
let context = request_context("legacy_sqlite_reader", "user");
|
||||
let context = request_context("legacy_control_plane_reader", "user");
|
||||
let (_, _, bytes) = open_local_file(
|
||||
State(state),
|
||||
Extension(context),
|
||||
@@ -12799,8 +12786,8 @@ fn main() {}
|
||||
}),
|
||||
)
|
||||
.await
|
||||
.expect("legacy sqlite read grant can open local file");
|
||||
assert_eq!(bytes, b"hello legacy sqlite");
|
||||
.expect("legacy control-plane read grant can open local file");
|
||||
assert_eq!(bytes, b"hello legacy control plane");
|
||||
assert!(!policy_file.exists(), "SQLite grant 不应写旧 JSON policy");
|
||||
|
||||
std::env::remove_var("MNOTE_LOCAL_ACCESS_POLICY_FILE");
|
||||
@@ -12809,10 +12796,10 @@ fn main() {}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn local_resource_write_allows_sqlite_directory_write_grant_without_json_policy() {
|
||||
async fn local_resource_write_allows_control_plane_directory_write_grant_without_json_policy() {
|
||||
let _guard = env_lock().lock().expect("env lock");
|
||||
let root = temp_root("mnote-local-resource-write-sqlite-grant-root");
|
||||
let policy_root = temp_root("mnote-local-resource-write-sqlite-grant-config");
|
||||
let root = temp_root("mnote-local-resource-write-control-plane-grant-root");
|
||||
let policy_root = temp_root("mnote-local-resource-write-control-plane-grant-config");
|
||||
let policy_file = policy_root.join("missing-access-policy.json");
|
||||
let state = test_state();
|
||||
let root_uri = format!("file://{}", root.display());
|
||||
@@ -12822,18 +12809,18 @@ fn main() {}
|
||||
state
|
||||
.control_plane()
|
||||
.upsert_user(UpsertUserInput {
|
||||
id: Some("sqlite_writer".into()),
|
||||
email: Some("sqlite-writer@example.com".into()),
|
||||
username: "sqlite_writer".into(),
|
||||
display_name: "sqlite_writer".into(),
|
||||
id: Some("control_plane_writer".into()),
|
||||
email: Some("control-plane-writer@example.com".into()),
|
||||
username: "control_plane_writer".into(),
|
||||
display_name: "control_plane_writer".into(),
|
||||
role: None,
|
||||
password_hash: None,
|
||||
})
|
||||
.expect("upsert sqlite writer");
|
||||
.expect("upsert control-plane writer");
|
||||
state
|
||||
.control_plane()
|
||||
.grant_directory_access(DirectoryGrantInput {
|
||||
user_id: "sqlite_writer".into(),
|
||||
user_id: "control_plane_writer".into(),
|
||||
workspace_id: None,
|
||||
root_uri: root_uri.clone(),
|
||||
root_path: root
|
||||
@@ -12847,9 +12834,9 @@ fn main() {}
|
||||
source: "test".into(),
|
||||
created_by: None,
|
||||
})
|
||||
.expect("grant sqlite write");
|
||||
.expect("grant control-plane write");
|
||||
|
||||
let context = request_context("sqlite_writer", "user");
|
||||
let context = request_context("control_plane_writer", "user");
|
||||
let (_, _, payload) = write_local_resource(
|
||||
State(state),
|
||||
Extension(context),
|
||||
@@ -12868,7 +12855,7 @@ fn main() {}
|
||||
}),
|
||||
)
|
||||
.await
|
||||
.expect("sqlite write grant can write local resource");
|
||||
.expect("control-plane write grant can write local resource");
|
||||
assert_eq!(payload["ok"], true);
|
||||
let written = std::fs::read_to_string(root.join("README.md")).expect("read file");
|
||||
assert!(written.contains("new content"));
|
||||
|
||||
Reference in New Issue
Block a user