chore: align local-first control plane and editor fixes
- wire SQLite control-plane access/session paths into Rust web local-folder routes - preserve local Markdown attachment semantics across upload, reload, and secondary-pane resource tabs - refresh design governance docs, Reasonix task templates, and bug records - retire root .mcp.json local MCP config
This commit is contained in:
@@ -111,6 +111,7 @@ pub(crate) const ADMIN_POLICY_SCRIPT: &str = r#"
|
||||
var deleteShareGrantResult = root.querySelector('[data-testid="mnote-admin-delete-share-grant-result"]');
|
||||
var refreshShareGrantsButton = root.querySelector('[data-admin-action="refresh-share-grants"]');
|
||||
var shareGrantsList = root.querySelector('[data-testid="mnote-admin-share-grants-list"]');
|
||||
var currentActorId = document.body && document.body.getAttribute ? String(document.body.getAttribute('data-mnote-actor-id') || '').trim() : '';
|
||||
var pageConfig = (function () {
|
||||
var node = root.querySelector('#__MNOTE_ACCESS_POLICY_PAGE__');
|
||||
try { return JSON.parse(node ? node.textContent || '{}' : '{}'); } catch (_) { return {}; }
|
||||
@@ -147,6 +148,48 @@ pub(crate) const ADMIN_POLICY_SCRIPT: &str = r#"
|
||||
return suffix ? base + suffix : base;
|
||||
}
|
||||
|
||||
function pathToFileRootUri(value) {
|
||||
var trimmed = String(value || '').trim();
|
||||
if (!trimmed) return '';
|
||||
if (/^file:\/\//i.test(trimmed)) return trimmed;
|
||||
if (trimmed.charAt(0) !== '/') return '';
|
||||
return 'file://' + trimmed.split('/').map(function(part, index) {
|
||||
return index === 0 ? '' : encodeURIComponent(part);
|
||||
}).join('/');
|
||||
}
|
||||
|
||||
function localFolderOpenHref(grant) {
|
||||
var rootUri = String(grant.rootUri || '').trim();
|
||||
if (rootUri && !/^file:\/\//i.test(rootUri)) rootUri = '';
|
||||
if (!rootUri) {
|
||||
var rootPath = String(grant.rootPath || '').trim();
|
||||
if (rootPath) rootUri = pathToFileRootUri(rootPath);
|
||||
}
|
||||
if (!rootUri) {
|
||||
rootUri = pathToFileRootUri(String(grant.rootUri || '').trim());
|
||||
}
|
||||
if (!rootUri) return '';
|
||||
var url = new URL('/', window.location.origin);
|
||||
url.searchParams.set('treeView', 'filetree');
|
||||
url.searchParams.set('sourceKind', 'local_folder');
|
||||
url.searchParams.set('rootUri', rootUri);
|
||||
return url.pathname + url.search;
|
||||
}
|
||||
|
||||
function isDefaultWorkspaceAutoGrant(grant) {
|
||||
var source = String(grant && grant.source || '').trim();
|
||||
var workspaceId = String(grant && grant.workspaceId || '').trim();
|
||||
var rootUri = String(grant && grant.rootUri || '').trim();
|
||||
var permission = String(grant && grant.permission || '').trim();
|
||||
var createdBy = String(grant && (grant.createdBy || grant.ownerUserId) || '').trim();
|
||||
var targetUser = String(grant && (grant.userId || grant.targetUserId) || '').trim();
|
||||
return source === 'auto'
|
||||
&& workspaceId
|
||||
&& permission === 'write'
|
||||
&& createdBy === targetUser
|
||||
&& /^local:\/\/users\/.+\/workspaces\/my-space$/.test(rootUri);
|
||||
}
|
||||
|
||||
function renderShareGrants(payload) {
|
||||
if (!shareGrantsList) return;
|
||||
var grants = readDirectoryGrants(payload);
|
||||
@@ -156,12 +199,20 @@ pub(crate) const ADMIN_POLICY_SCRIPT: &str = r#"
|
||||
}
|
||||
shareGrantsList.innerHTML = grants.map(function(grant) {
|
||||
var active = grant.active === false || grant.status === 'revoked' ? '已撤销' : '有效';
|
||||
var revokeButton = grant.active === false ? '' :
|
||||
var openHref = localFolderOpenHref(grant);
|
||||
var rootLabel = escapeHtml(grant.rootPath || grant.rootUri || '');
|
||||
var createdBy = String(grant.createdBy || grant.ownerUserId || '').trim();
|
||||
var systemOwned = isDefaultWorkspaceAutoGrant(grant);
|
||||
var canRevoke = !systemOwned && (isAdmin || (createdBy && currentActorId && createdBy === currentActorId));
|
||||
var rootNode = openHref
|
||||
? '<a class="mnote-admin-policy-root-link" data-testid="mnote-admin-open-granted-root" href="' + escapeHtml(openHref) + '">' + rootLabel + '</a>'
|
||||
: '<strong>' + rootLabel + '</strong>';
|
||||
var revokeButton = grant.active === false || !canRevoke ? '' :
|
||||
'<button type="button" data-admin-action="revoke-access-grant" data-grant-id="' + escapeHtml(grant.id || '') + '">撤销</button>';
|
||||
return '<article class="mnote-admin-policy-row">' +
|
||||
'<div><strong>' + escapeHtml(grant.rootPath || grant.rootUri || '') + '</strong><span>授权用户 ' + escapeHtml(grant.targetUserId || grant.userId || '') + '</span></div>' +
|
||||
'<div>' + rootNode + '<span>授权用户 ' + escapeHtml(grant.targetUserId || grant.userId || '') + '</span></div>' +
|
||||
'<div>' + renderBadge(grant.permission) + renderBadge(active) + '</div>' +
|
||||
'<div><span>创建者 ' + escapeHtml(grant.createdBy || grant.ownerUserId || '') + '</span><span>授权 ID ' + escapeHtml(grant.id || '') + '</span>' + revokeButton + '</div>' +
|
||||
'<div><span>创建者 ' + escapeHtml(createdBy) + '</span><span>授权 ID ' + escapeHtml(grant.id || '') + '</span>' + revokeButton + '</div>' +
|
||||
'</article>';
|
||||
}).join('');
|
||||
}
|
||||
@@ -203,7 +254,8 @@ pub(crate) const ADMIN_POLICY_SCRIPT: &str = r#"
|
||||
|
||||
root.querySelector('[data-admin-form="create-share-grant"]').addEventListener('submit', function (event) {
|
||||
event.preventDefault();
|
||||
var values = shareGrantFormValues(event.currentTarget);
|
||||
var form = event.currentTarget;
|
||||
var values = shareGrantFormValues(form);
|
||||
setText(createShareGrantResult, '正在创建...');
|
||||
requestJson(accessPolicyUrl('/grants'), {
|
||||
method: 'POST',
|
||||
@@ -211,7 +263,7 @@ pub(crate) const ADMIN_POLICY_SCRIPT: &str = r#"
|
||||
}).then(function (payload) {
|
||||
setText(createShareGrantResult, payload);
|
||||
setText(shareGrantsMessage, '文件夹授权已创建');
|
||||
event.currentTarget.reset();
|
||||
form.reset();
|
||||
return refreshShareGrants();
|
||||
}).catch(function (error) {
|
||||
setText(createShareGrantResult, { ok: false, error: error.message || '创建失败' });
|
||||
@@ -292,4 +344,20 @@ mod tests {
|
||||
assert!(!html.contains("capabilities"));
|
||||
assert!(!html.contains("mnote-admin-validate-root-submit"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_policy_script_keeps_form_reference_for_async_reset() {
|
||||
assert!(ADMIN_POLICY_SCRIPT.contains("var form = event.currentTarget;"));
|
||||
assert!(ADMIN_POLICY_SCRIPT.contains("form.reset();"));
|
||||
assert!(!ADMIN_POLICY_SCRIPT.contains("event.currentTarget.reset();"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_policy_script_links_grants_to_local_folder_entry() {
|
||||
assert!(ADMIN_POLICY_SCRIPT.contains("function localFolderOpenHref(grant)"));
|
||||
assert!(ADMIN_POLICY_SCRIPT.contains("sourceKind', 'local_folder'"));
|
||||
assert!(ADMIN_POLICY_SCRIPT.contains("data-testid=\"mnote-admin-open-granted-root\""));
|
||||
assert!(ADMIN_POLICY_SCRIPT.contains("function isDefaultWorkspaceAutoGrant(grant)"));
|
||||
assert!(ADMIN_POLICY_SCRIPT.contains("var canRevoke = !systemOwned &&"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user