Skip to content

fix(perm): qualify native writes for V2 directory shares without library grants - #19

Merged
servicememeai merged 10 commits into
devfrom
fix/native-share-write
Oct 20, 2026
Merged

servicememeai merged 10 commits into
devfrom
fix/native-share-write

Conversation

@servicememeai

Copy link
Copy Markdown

Purpose

Close the native C permission gate for accounts with directory-only r/rw shares. This is a path-specific fallback only after native repo permission is absent, never after native RPC failures, and never admin.

Change

  • New CfShareGrantFunc invokes Hub's authenticated /cloudfile/acl/check/ to retrieve the exact r/rw level for a scoped path.
  • Keep the existing permission-tightening chain and C/Go final publication checks unchanged.
  • Repair standard V2 registration: auto-detect cf_library_storage, cf_dir_acl, cf_sso_group_map at startup (instead of retired cf_managed_library/cf_schema_migration); avoid an extra configuration switch. On missing schema/Hub channel the native denial remains.
  • Extend bounded production-function fixture tests for path, level, outage/denial distinctions, schema and Hub-channel registration.

Dependency / ordering

Merge Hub #40 first. An old Hub that lacks permissions fails closed and cannot qualify share-only writes.

Validation boundary

Targeted source/test fixtures provided; request lightweight PR source CI only. No full build, no database changes, no DEV deployment. Legacy cf_managed_library access-token restrictions remain intentionally intact; validate those separately before rollout.

opendev9 and others added 8 commits October 20, 2026 23:43
Hub's /cloudfile/acl/* endpoints already accept a share root for an account
with no library membership (f8a396a46), but every native write entry still went
through seafile_check_permission_by_path(), which returned NULL as soon as
repo-perm.c answered "no permission". Upload links, mkdir, rename, move, delete
and seafdav were therefore refused before the Hub was ever asked: a shared user
could browse and download but never write.

The tightening chain cannot close this. It starts from a native grant, each
provider may only reduce it, and a NULL native permission ends it -- a directory
share is the opposite case, since the account is deliberately not a member. So
it gets a second, explicitly named seam instead of a special case in every
provider.

- cf-ext: add CfShareGrantFunc / cf_ext_share_grant(), consulted only after the
  native gate *denied*; an RPC error is propagated rather than retried as a
  share question. A capability answers r or rw for that exact path and can
  never answer admin.
- cf-v2-share: ask the Hub's internal check endpoint, reusing the transport
  extracted from cf-v2-acl.c as cf_v2_acl_check_json() so the JWT handshake has
  one implementation. Registered only where the managed schema and an internal
  channel exist; [cloudfile] dir_share_native_grant defaults on, because a
  capability that fixes a denial hole must not be silently off.
- The library root and every unshared path stay denied, and the C/Go final
  publication checks are untouched.

The Hub must send the per-check `permissions` field this reads. Without it the
answer is "cannot qualify", never "assume rw".

Tests: the existing check_permission_by_path fixture gains the fallback cases
(denial vs failure, member path never asks, managed boundary not reopened);
tests/cf-dir-share proves the request shape, path normalization, r/rw mapping
and the deny/outage distinction against a fake Hub channel.
@servicememeai
servicememeai merged commit 06efc4d into dev Oct 20, 2026
1 check passed
@opendev9
opendev9 deleted the fix/native-share-write branch October 21, 2026 00:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants