mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-01 13:47:51 +00:00
88c873ecd4fbcce342dba0b73fe3671c4ea35313
10
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4a2879abad |
admin: show a copyable S3 object URL in the bucket file browser (#10933)
* admin: offer copyable S3 object URLs in the bucket file browser * admin: hide object urls when the bucket type lookup fails * admin: ignore an s3.public_endpoint that is not an absolute http url * mini: build the seeded s3 endpoint with JoinHostPort for ipv6 * admin: reject a query or fragment in s3.public_endpoint * mini: drop the seeded s3 endpoint when a later run disables s3 * admin: reject userinfo and bare delimiters in s3.public_endpoint, redact the warning * mini: pass its s3 endpoint as an admin option instead of mutating viper * admin: keep the rejected s3.public_endpoint value out of the log |
||
|
|
641fc8b031 |
admin: add visual iam policy editor (#10878)
* admin: add visual iam policy editor Add a structured, tabbed editor (Editor / JSON) for creating and editing IAM policies in the admin dashboard, alongside the existing raw-JSON textarea: - policies.templ: per-statement cards for Sid, Effect, Action, and Resource, with unmanaged fields (Principal, NotPrincipal, NotResource, Condition, or anything else) preserved verbatim in a per-statement "advanced fields" JSON box so nothing is lost on round-trip. Switching tabs commits and reparses in both directions. Restored the "Use Sample Policy" button, now filling both the structured editor and the JSON tab. The "Validate" button now calls the existing but previously unused POST /api/object-store/policies/validate endpoint instead of doing JS-only checks. - Progressive Resource ARN autocomplete: suggests bucket names first, then once "bucket/" is typed, suggests bucket/* plus the bucket's direct subfolders, drilling down one path segment at a time as the user types further "/" characters. - New GET /api/files/list-folders endpoint (file_browser_handlers.go) backing the folder autocomplete: wraps the existing file browser data function and returns just the subdirectory names as JSON, scoped to paths under /buckets. - Action-name suggestions (datalist) for the Action field, sourced from the existing s3_constants.S3_ACTION_* constants plus new s3_constants.S3TABLES_ACTION_* constants (extracted from the s3tables operation dispatch switch) so the suggestion list can't drift from the strings the engines actually understand. - policy_handlers.go: ValidatePolicy now accepts a statement with only NotResource set (previously required Resource), matching policy_engine.validateStatement and the fact the new editor makes such statements reachable from the UI. - Tests: ValidatePolicy behavior, route registration for the policy API and the new list-folders endpoint, list-folders path scoping, and the action-suggestion list's shape. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * admin: fix XSS, cache poisoning, and cap overshoot in policy editor Address code review findings on the IAM policy editor added in the previous commit: - policies.templ (displayPolicyDetails): escape every interpolated policy value (Sid, Effect, Action, Resource, policy name, and the raw JSON document) before assigning to innerHTML. Policy documents can come from other admins or an import, so an unescaped field could execute script when the "View" modal renders it. - policies.templ (policyEditorStateToDoc): reject JSON arrays in a statement's "advanced fields" box, not just invalid JSON. `typeof [] === 'object'` was true, so a JSON array was assigned to the statement; subsequent property assignments (Sid, Effect, ...) landed on the array object but JSON.stringify of an array only serializes numeric indices, silently dropping them. - policies.templ (loadPolicyFolderNames): on a failed folder lookup, remove the cache entry instead of permanently caching the empty fallback, so a transient network/server error doesn't block retries for the rest of the page's lifetime. - file_browser_handlers.go (ListFolders): stop appending directory names as soon as the running count reaches maxListFoldersEntries, instead of only checking the cap after a full page is processed, so the returned list never exceeds the configured cap. Regenerated policies_templ.go with the already-stamped templ v0.3.1001 to keep the diff scoped to this file. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * admin: stop policy editor from clobbering the active tab and dropping malformed advanced fields Address two review findings on the IAM policy editor (Issue 3, stored-XSS in displayPolicyDetails, was already fixed by the previous commit and is unchanged here): - createPolicy, updatePolicy, and validatePolicyDocument always committed the structured editor's (possibly stale) state into the JSON textarea before submitting, even when the user had just edited the JSON tab directly. That silently discarded the user's JSON edits and validated/saved the old structured-editor state instead, which could leave broader permissions in force than intended. Added commitPolicyActiveTab(which), which commits whichever tab is currently visible into the other side instead of unconditionally overwriting the JSON tab from the editor: if the JSON tab is active it parses that JSON back into the structured editor (without touching the textarea itself), otherwise it serializes the structured editor into the textarea as before. All three call sites, plus the JSON-tab "show.bs.tab" handler, now use this and abort with an alert if the currently active tab's content can't be committed. - policyEditorStateToDoc silently continued with an empty object when a statement's "advanced fields" box held invalid JSON, so switching tabs, validating, or saving would drop Principal/NotResource/Condition from that statement without telling the user. It now throws (with the statement number and parse error) on invalid or non-object JSON there, and callers surface that via showAlert and abort instead of proceeding. Regenerated policies_templ.go with the already-stamped templ v0.3.1001. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * admin: keep unmanaged top-level policy fields across editor tab switches policyDocToEditorState only carried Version and Statement into editor state, so any other top-level key (e.g. Id) present in the JSON tab was silently rewritten away as soon as the user switched to the Editor tab and back. Capture those keys in state.otherFields and merge them back in policyEditorStateToDoc before Version and Statement are written, so the two tabs stay faithful to each other and the editor never rewrites text the user typed. Note this is editor fidelity only: the admin API's policy_engine.PolicyDocument carries just Version and Statement, and DocumentJSON is never populated, so such fields are still discarded by the server once a policy is saved. Making them survive a save would require a backend change, which is out of scope here. Regenerated policies_templ.go with the already-stamped templ v0.3.1001. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * admin: warn before a policy save discards unsupported top-level fields The editor round-trips unmanaged top-level keys (e.g. Id) between the Editor and JSON tabs, but the admin API's policy_engine.PolicyDocument carries only Version and Statement, so the server drops them on save and the user saw no indication. Added confirmPolicyFieldDiscard(), called from createPolicy and updatePolicy after the active tab is committed (so the field list is accurate whichever tab is showing). It names the fields that will be lost and lets the user confirm or cancel. Not wired into validatePolicyDocument, which doesn't persist anything. Chose the warning over the alternative of persisting these fields through the backend: policy_engine.PolicyDocument is shared by the S3 bucket-policy engine and IAM evaluation, so extending it would change the stored document shape for every policy in the codebase - far beyond the scope of this editor. Regenerated policies_templ.go with the already-stamped templ v0.3.1001. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * admin: reject malformed Effect and Resource/NotResource conflicts in policy editor Two review findings on the IAM policy editor: - policyDocToEditorState defaulted any non-"Deny" Effect (missing, misspelled, wrong case) to "Allow". A statement meant to be "Deny" with a typo like "deny" would silently become a permissive "Allow" instead of being rejected. It now throws on anything but an exact "Allow" or "Deny", naming the offending statement and value. commitPolicyTextareaToEditor catches this the same way it already catches invalid JSON: alert the user and keep the JSON tab active instead of switching to the Editor tab with wrong data. - policyEditorStateToDoc could save a statement with both Resource (from the structured field) and NotResource (surviving in the "advanced fields" extras from before the user switched to using Resource) set at once - a contradictory combination neither the admin's ValidatePolicy handler nor policy_engine's evaluator rejected. When the structured Resource field is non-empty it now deletes any leftover NotResource from extras, consistent with the file's existing rule that structured fields take precedence over extras. Mirrored the existing Principal/NotPrincipal exclusivity check in weed/admin/handlers/policy_handlers.go's ValidatePolicy to reject the same combination server-side, since create/update perform no validation at all. Deliberately left policy_engine.validateStatement (used by the S3 bucket-policy PUT handler for every bucket policy in the product) unchanged - extending that shared validator is a larger, separate change outside this admin-editor fix's scope. Added a handler test for the new Resource+NotResource rejection. Regenerated policies_templ.go with the already-stamped templ v0.3.1001. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * admin: add NotResource support to the visual policy editor Since Resource and NotResource are mutually exclusive (enforced by a previous fix), NotResource could previously only be set through the raw JSON in a statement's "advanced fields" box. Promote it to a first-class mode of the structured editor: - The static "Resources" label is now a Resource/NotResource dropdown; the same list of values underneath is reused for either key depending on the selected mode, with a short form-text explaining the semantics. - NotResource is added to POLICY_STATEMENT_KNOWN_KEYS, since it's now a managed field like Resource rather than something that falls through to extras. - policyDocToEditorState derives resourceMode from which key is present on load, and throws (same handling as the existing malformed-Effect case: alert, keep the JSON tab active) if a hand-edited document has both Resource and NotResource on one statement, since that can't be represented by the dropdown. - policyEditorStateToDoc writes only the key matching the selected mode, replacing the previous one-directional "delete NotResource whenever Resource is set" fix with mode-driven logic that also deletes Resource when NotResource is selected. - displayPolicyDetails (the read-only View modal) now shows the actual NotResource values with a distinct label instead of a static "(NotResource used instead)" placeholder. No backend changes: the server-side "cannot specify both" check added previously in policy_handlers.go's ValidatePolicy already covers this. Regenerated policies_templ.go with the already-stamped templ v0.3.1001. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eb2a51LciCsyY35sqDoGNe * admin: reject non-object policy documents; catch Principal/NotPrincipal conflicts server-side Two review findings: - policyDocToEditorState treated a top-level JSON value that wasn't an object (null, or a bare string/number/boolean) as an empty statement list instead of failing explicitly. If the user typed e.g. "hello" or 42 in the JSON tab and switched to the Editor tab, their input was silently discarded and replaced with an empty policy - the same class of "guess instead of reject" bug fixed for malformed Effect and Resource/NotResource conflicts previously. Added an explicit check that throws for null/scalar input, while leaving array and object document shapes accepted exactly as before. - weed/admin/handlers/policy_handlers.go's ValidatePolicy checked the Resource/NotResource conflict by non-empty length (len(...Strings()) > 0), which misses a statement where Resource is explicitly present but an empty list (e.g. "Resource": []) alongside a non-empty NotResource. Switched that check to field presence (!= nil), matching how policy_engine's own validateStatement already treats Principal/NotPrincipal exclusivity. Also added the equivalent Principal/NotPrincipal presence check to this handler, which had none before - the advanced-fields box in the visual editor lets a user set both today, and nothing server-side caught it. The existing non-empty "Resource or NotResource is required" check is left as a length check, since an empty array shouldn't count as "provided". Added test cases for both conflict checks in policy_handlers_test.go. Regenerated policies_templ.go with the already-stamped templ v0.3.1001. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eb2a51LciCsyY35sqDoGNe * admin: add Principal/NotPrincipal support to the visual policy editor (v1, AWS-only) Adds a first, deliberately narrow structured editor for a statement's Principal/NotPrincipal, left out when NotResource support was added: - A Principal/NotPrincipal mode dropdown mirrors the existing Resource/NotResource one (same mutual-exclusivity handling: the two fields can't be set at once, and switching modes reuses the same value list). - A simple repeatable text-value list feeds a single {"AWS": [...]} object on save - always the AWS type, never the "bare" (untyped) SeaweedFS-extension shape. Per policy_engine's allowedPrincipalKeys, Service/Federated/CanonicalUser also parse successfully, but nothing in the S3 bucket-policy evaluation path ever sets a real caller's principal to a service name, an OIDC provider ARN, or a canonical user ID, so only AWS is functionally meaningful today - out of scope for this v1. - On load, only the exact {"AWS": ...} single-key shape is unwrapped into the structured field and removed from "extras". Anything else (bare string/array, a different single type key, or several type keys at once) is left untouched in "extras" exactly as before, with a visible warning under the dropdown so the user knows a Principal/NotPrincipal exists but isn't shown there. Saving with the structured field left empty never touches whatever's already in extras, so a preserved complex form isn't silently dropped just because the user didn't touch this field. - The read-only View modal now displays Principal/NotPrincipal for any shape (via a small generic summarizer), not just the AWS-simple one. - Generalized the action/resource field-to-state-key mapping (used by commitPolicyEditorForm and the add/remove-item click handler) into a shared lookup table instead of stacking another ternary, now that a third field (principal) exists. Regenerated policies_templ.go with the already-stamped templ v0.3.1001. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eb2a51LciCsyY35sqDoGNe * admin: support the bare "*" wildcard Principal in the visual editor "Principal": "*" (and NotPrincipal: "*") is the standard AWS shorthand for "everyone" and is common in real bucket policies, but the v1 Principal/NotPrincipal editor only recognized the {"AWS": ...} object form, leaving a bare "*" statement's principal hidden in Advanced fields. parseSimpleAwsPrincipal now also accepts the bare string "*" as a simple, structurally-editable value. On save, a principal value list containing exactly ["*"] is written back as the bare "*" string (matching the common convention) rather than wrapped as {"AWS": "*"}; anything else still wraps under AWS as before. Updated the field's form-text hint accordingly. Regenerated policies_templ.go with the already-stamped templ v0.3.1001. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eb2a51LciCsyY35sqDoGNe * admin: add Principal field autocomplete backed by users + IAM roles Adds a datalist-backed autocomplete for the policy editor's Principal/ NotPrincipal text fields, sourced from a new API listing existing identities: - weed/admin/dash/principal_suggestions.go: AdminServer.GetPrincipalSuggestions combines S3 user ARNs (via the existing GetObjectStoreUsers + iam.UserArn) with IAM role ARNs (via integration.NewFilerRoleStore / ListRoles, reusing the exact same construction already used in iam_manager.go - no new dependency risk introduced). Role ARNs are reconstructed from the role name using SeaweedFS's default arn:aws:iam::role/<name> convention rather than fetching each role's stored definition, since this only backs a suggestion list. Role listing failures are logged and swallowed rather than failing the whole request - an incomplete suggestion list is fine, blocking policy editing over it is not. Service accounts are deliberately not listed separately: a service account's ARN is identical to its parent user's, already covered by the user list. - weed/admin/handlers/policy_handlers.go: GetPrincipalSuggestions handler exposing this as {"principals": [...]}. - Route registered at the API root (GET /api/principals) rather than under policyApi's "/object-store/policies" prefix, since that subrouter's existing "/{name}" GET route would shadow any single-segment GET route registered after it (the same class of gotcha previously seen with "/validate"). - weed/admin/view/app/policies.templ: a shared, lazily-fetched-once policyPrincipalSuggestions datalist (flat list - unlike the progressive per-folder Resource ARN autocomplete, users/roles aren't hierarchical), wired into policyListRowHtml for field:"principal" and populated on input/focus, with "*" always offered first. Added tests for the new ARN-construction helper and route registration. Regenerated policies_templ.go with the already-stamped templ v0.3.1001. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eb2a51LciCsyY35sqDoGNe * admin: fix fieldset/legend styling in the structured policy editor Bootstrap's form reset stretches <legend> to the fieldset's full width (float: left; width: 100%), which loses the native "notch in the border" look and makes each section's label bar as wide as the card. Add two scoped classes: .policy-stmt-fieldset (border, rounded corners, spacing between sections) and .policy-stmt-legend (undoes the float/width so the legend hugs its content, with a little padding). Applied to the three per-statement sections (Actions, Resource/NotResource, Principal/NotPrincipal), replacing the ad hoc "border rounded" utility classes that were doubling up with the fieldset's own border. Also gave the "Advanced fields" <details> a small top margin to match the new spacing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eb2a51LciCsyY35sqDoGNe * admin: suggest bucket/* alongside the bucket itself in Resource autocomplete At the bucket-name stage of the Resource field's progressive autocomplete, only "arn:aws:s3:::bucket" was offered. Add "arn:aws:s3:::bucket/*" right alongside it, since granting access to everything in a bucket is the more common case and previously required typing a "/" first to reach the folder-level "*" suggestion. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eb2a51LciCsyY35sqDoGNe * admin: keep an unparseable policy in the JSON tab instead of wiping it editPolicy() built the structured state inside the fetch .then, so a policy the editor cannot model threw into the sibling .catch, which alerted and called hide(). Showing the alert at that moment left the modal on screen with an empty editor and the document only in the JSON tab, and Save Changes then serialized the empty state over the policy. Reachable two ways, since neither create path rejects these: the admin API never validates on create, so "Effect":"allow" is stored as typed, and policy_engine.validateStatement lets Resource and NotResource sit in the same statement. Hand the document to the JSON tab instead, which is what that tab is for, and mark the state so nothing serializes the placeholder over it. * admin: validate a policy document before saving it Validation was wired only to the Validate button, so nothing stopped a document the server's own validator rejects from being stored. With the structured editor supplying the boilerplate and required dropped from the textarea, opening the modal, typing a name and clicking Create Policy was enough to save a statement-less policy. Share validatePolicyJSON with the two save paths and abort on failure. * admin: bound the folder autocomplete listing maxListFoldersEntries caps the folders collected, but nothing capped the entries paged through to find them, so a bucket holding only flat object keys - no subfolders to count - was walked to the end, 200 entries per round trip, behind one keystroke. Measured against an in-process filer: 6 entries 0.5ms, 3k entries 7.7ms, 30k entries 53ms, all of it linear in the directory rather than in the answer. Cap the scan as well, and let GetFileBrowser take a prefix so the segment the user is still typing is filtered by the filer instead of by paging. The same 30k directory now answers in 0.6ms once a prefix is typed. * admin: clean the path before scoping list-folders to /buckets util.CleanWindowsPath only rewrites backslashes, so "/buckets/../etc" walked straight past the prefix check the endpoint relies on for its scope. Nothing leaked - filer paths are literal keys, so the traversal resolved to nothing - but the check reads as a boundary and wasn't one, and the test asserting it didn't cover the one input that would try. validateAndCleanFilePath in the same file already does this. * admin: stringify policy values before escaping them escapeHtml calls text.replace directly, and the Sid, the per-item action and resource inputs, and the View modal's Resource/NotResource all pass values straight out of JSON.parse. A policy carrying "Sid": 5 or "Action": [1] threw "text.replace is not a function" and took the render with it. escapedJoin already coerced; use it everywhere and coerce the editor state at the point it's built. * admin: only show the NotResource hint in NotResource mode The hint rendered unconditionally, so it sat under a selector reading "Resource" telling the user the statement applies to everything except what they'd listed. Redraw the card when the selector changes so it follows the mode. --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Chris Lu <chris.lu@gmail.com> |
||
|
|
db34e8b6fd |
feat(admin): prefer stored S3 Content-Type metadata over key-extension MIME inference (#9286)
* feat(admin): prefer stored filer mime in file browser and properties * feat(mime): enhance MIME type registration and improve fallback logic Co-authored-by: Copilot <copilot@github.com> --------- Co-authored-by: baracudaz <baracudaz@users.noreply.github.com> Co-authored-by: Copilot <copilot@github.com> |
||
|
|
e6ee293c17 |
Add table operations test (#8241)
* Add Trino blog operations test * Update test/s3tables/catalog_trino/trino_blog_operations_test.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * feat: add table bucket path helpers and filer operations - Add table object root and table location mapping directories - Implement ensureDirectory, upsertFile, deleteEntryIfExists helpers - Support table location bucket mapping for S3 access * feat: manage table bucket object roots on creation/deletion - Create .objects directory for table buckets on creation - Clean up table object bucket paths on deletion - Enable S3 operations on table bucket object roots * feat: add table location mapping for Iceberg REST - Track table location bucket mappings when tables are created/updated/deleted - Enable location-based routing for S3 operations on table data * feat: route S3 operations to table bucket object roots - Route table-s3 bucket names to mapped table paths - Route table buckets to object root directories - Support table location bucket mapping lookup * feat: emit table-s3 locations from Iceberg REST - Generate unique table-s3 bucket names with UUID suffix - Store table metadata under table bucket paths - Return table-s3 locations for Trino compatibility * fix: handle missing directories in S3 list operations - Propagate ErrNotFound from ListEntries for non-existent directories - Treat missing directories as empty results for list operations - Fixes Trino non-empty location checks on table creation * test: improve Trino CSV parsing for single-value results - Sanitize Trino output to skip jline warnings - Handle single-value CSV results without header rows - Strip quotes from numeric values in tests * refactor: use bucket path helpers throughout S3 API - Replace direct bucket path operations with helper functions - Leverage centralized table bucket routing logic - Improve maintainability with consistent path resolution * fix: add table bucket cache and improve filer error handling - Cache table bucket lookups to reduce filer overhead on repeated checks - Use filer_pb.CreateEntry and filer_pb.UpdateEntry helpers to check resp.Error - Fix delete order in handler_bucket_get_list_delete: delete table object before directory - Make location mapping errors best-effort: log and continue, don't fail API - Update table location mappings to delete stale prior bucket mappings on update - Add 1-second sleep before timestamp time travel query to ensure timestamps are in past - Fix CSV parsing: examine all lines, not skip first; handle single-value rows * fix: properly handle stale metadata location mapping cleanup - Capture oldMetadataLocation before mutation in handleUpdateTable - Update updateTableLocationMapping to accept both old and new locations - Use passed-in oldMetadataLocation to detect location changes - Delete stale mapping only when location actually changes - Pass empty string for oldLocation in handleCreateTable (new tables have no prior mapping) - Improve logging to show old -> new location transitions * refactor: cleanup imports and cache design - Remove unused 'sync' import from bucket_paths.go - Use filer_pb.UpdateEntry helper in setExtendedAttribute and deleteExtendedAttribute for consistent error handling - Add dedicated tableBucketCache map[string]bool to BucketRegistry instead of mixing concerns with metadataCache - Improve cache separation: table buckets cache is now separate from bucket metadata cache * fix: improve cache invalidation and add transient error handling Cache invalidation (critical fix): - Add tableLocationCache to BucketRegistry for location mapping lookups - Clear tableBucketCache and tableLocationCache in RemoveBucketMetadata - Prevents stale cache entries when buckets are deleted/recreated Transient error handling: - Only cache table bucket lookups when conclusive (found or ErrNotFound) - Skip caching on transient errors (network, permission, etc) - Prevents marking real table buckets as non-table due to transient failures Performance optimization: - Cache tableLocationDir results to avoid repeated filer RPCs on hot paths - tableLocationDir now checks cache before making expensive filer lookups - Cache stores empty string for 'not found' to avoid redundant lookups Code clarity: - Add comment to deleteDirectory explaining DeleteEntry response lacks Error field * go fmt * fix: mirror transient error handling in tableLocationDir and optimize bucketDir Transient error handling: - tableLocationDir now only caches definitive results - Mirrors isTableBucket behavior to prevent treating transient errors as permanent misses - Improves reliability on flaky systems or during recovery Performance optimization: - bucketDir avoids redundant isTableBucket call via bucketRoot - Directly use s3a.option.BucketsPath for regular buckets - Saves one cache lookup for every non-table bucket operation * fix: revert bucketDir optimization to preserve bucketRoot logic The optimization to directly use BucketsPath bypassed bucketRoot's logic and caused issues with S3 list operations on delimiter+prefix cases. Revert to using path.Join(s3a.bucketRoot(bucket), bucket) which properly handles all bucket types and ensures consistent path resolution across the codebase. The slight performance cost of an extra cache lookup is worth the correctness and consistency benefits. * feat: move table buckets under /buckets Add a table-bucket marker attribute, reuse bucket metadata cache for table bucket detection, and update list/validation/UI/test paths to treat table buckets as /buckets entries. * Fix S3 Tables code review issues - handler_bucket_create.go: Fix bucket existence check to properly validate entryResp.Entry before setting s3BucketExists flag (nil Entry should not indicate existing bucket) - bucket_paths.go: Add clarifying comment to bucketRoot() explaining unified buckets root path for all bucket types - file_browser_data.go: Optimize by extracting table bucket check early to avoid redundant WithFilerClient call * Fix list prefix delimiter handling * Handle list errors conservatively * Fix Trino FOR TIMESTAMP query - use past timestamp Iceberg requires the timestamp to be strictly in the past. Use current_timestamp - interval '1' second instead of current_timestamp. --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> |
||
|
|
2ee6e4f391 |
mount: refresh and evict hot dir cache (#8174)
* mount: refresh and evict hot dir cache * mount: guard dir update window and extend TTL * mount: reuse timestamp for cache mark * Apply suggestion from @gemini-code-assist[bot] Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * mount: make dir cache tuning configurable * mount: dedupe dir update notices * mount: restore invalidate-all cache helper * mount: keep hot dir tuning constants * mount: centralize cache state reset * mount: mark refresh completion time * mount: allow disabling idle eviction --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> |
||
|
|
79722bcf30 |
Add s3tables shell and admin UI (#8172)
* Add shared s3tables manager * Add s3tables shell commands * Add s3tables admin API * Add s3tables admin UI * Fix admin s3tables namespace create * Rename table buckets menu * Centralize s3tables tag validation * Reuse s3tables manager in admin * Extract s3tables list limit * Add s3tables bucket ARN helper * Remove write middleware from s3tables APIs * Fix bucket link and policy hint * Fix table tag parsing and nav link * Disable namespace table link on invalid ARN * Improve s3tables error decode * Return flag parse errors for s3tables tag * Accept query params for namespace create * Bind namespace create form data * Read s3tables JS data from DOM * s3tables: allow empty region ARN * shell: pass s3tables account id * shell: require account for table buckets * shell: use bucket name for namespaces * shell: use bucket name for tables * shell: use bucket name for tags * admin: add table buckets links in file browser * s3api: reuse s3tables tag validation * admin: harden s3tables UI handlers * fix admin list table buckets * allow admin s3tables access * validate s3tables bucket tags * log s3tables bucket metadata errors * rollback table bucket on owner failure * show s3tables bucket owner * add s3tables iam conditions * Add s3tables user permissions UI * Authorize s3tables using identity actions * Add s3tables permissions to user modal * Disambiguate bucket scope in user permissions * Block table bucket names that match S3 buckets * Pretty-print IAM identity JSON * Include tags in s3tables permission context * admin: refactor S3 Tables inline JavaScript into a separate file * s3tables: extend IAM policy condition operators support * shell: use LookupEntry wrapper for s3tables bucket conflict check * admin: handle buildBucketPermissions validation in create/update flows |
||
|
|
6de6061ce9 |
admin: add cursor-based pagination to file browser (#7891)
* adjust menu items * admin: add cursor-based pagination to file browser - Implement cursor-based pagination using lastFileName parameter - Add customizable page size selector (20/50/100/200 entries) - Add compact pagination controls in header and footer - Remove summary cards for cleaner UI - Make directory names clickable to return to first page - Support forward-only navigation (Next button) - Preserve cursor position when changing page size - Remove sorting to align with filer's storage order approach * Update file_browser_templ.go * admin: remove directory icons from breadcrumbs * Update file_browser_templ.go * admin: address PR comments - Fix fragile EOF check: use io.EOF instead of string comparison - Cap page size at 200 to prevent potential DoS - Remove unused helper functions from template - Use safer templ script for page size selector to prevent XSS * admin: cleanup redundant first button * Update file_browser_templ.go * admin: remove entry counting logic * admin: remove unused variables in file browser data * admin: remove unused logic for FirstFileName and HasPrevPage * admin: remove unused TotalEntries and TotalSize fields * Update file_browser_data.go |
||
|
|
9c784cf9e2 |
fix: use path to handle urls in weed admin file browser (#7858)
* fix: use path instead of filepath to handle urls in weed admin file browser * test: add comprehensive tests for file browser path handling - Test breadcrumb generation for various path scenarios - Test path handling with forward slashes (URL compatibility) - Test parent path calculation for Windows compatibility - Test file extension handling using path.Ext - Test bucket path detection logic These tests verify that the switch from filepath to path package works correctly and handles URLs properly across all platforms. * refactor: simplify fullPath construction using path.Join Replace verbose manual path construction with path.Join which: - Handles trailing slashes automatically - Is more concise and readable - Is more robust for edge cases * fix: normalize path in ShowFileBrowser and rename generateBreadcrumbs parameter Critical fix: - Add util.CleanWindowsPath() normalization to path parameter in ShowFileBrowser handler, matching the pattern used in other file operation handlers (lines 273, 464) - This ensures Windows-style backslashes are converted to forward slashes before processing, fixing path handling issues on Windows Consistency improvement: - Rename path parameter to dir in generateBreadcrumbs function - Aligns with parameter rename in GetFileBrowser for consistent naming throughout the file * test: improve coverage for Windows path handling and production code behavior Address reviewer feedback by enhancing test quality: 1. Improved test documentation: - Added clear comments explaining what each test validates - Clarified that some tests validate expected behavior vs production code - Documented the Windows path normalization flow 2. Enhanced actual production code testing: - TestGenerateBreadcrumbs: Calls actual production function - TestBreadcrumbPathFormatting: Validates production output format - TestDirectoryNavigation: Integration-style test for complete flow 3. Added new test functions for better coverage: - TestPathJoinHandlesEdgeCases: Verifies path.Join behavior - TestWindowsPathNormalizationBehavior: Documents expected normalization - TestDirectoryNavigation: Complete navigation flow test 4. Improved test organization: - Fixed duplicate field naming issues - Better test names for clarity - More comprehensive edge case coverage These improvements ensure the fix for issue #7628 (Windows path handling) is properly validated across the complete flow from handler to path logic. * test: use actual util.CleanWindowsPath function in Windows path normalization test Address reviewer feedback by testing the actual production function: - Import util package for CleanWindowsPath - Call the real util.CleanWindowsPath() instead of reimplementing logic - Ensures test validates actual implementation, not just expected behavior - Added more test cases for edge cases (simple path, deep nesting) This change validates that the Windows path normalization in the ShowFileBrowser handler (handlers/file_browser_handlers.go:64) works correctly with the actual util.CleanWindowsPath function. * style: fix indentation in TestPathJoinHandlesEdgeCases Align t.Errorf statement inside the if block with proper indentation. The error message now correctly aligns with the if block body, maintaining consistent indentation throughout the function. * test: restore backslash validation check in TestPathJoinHandlesEdgeCases --------- Co-authored-by: Chris Lu <chris.lu@gmail.com> |
||
|
|
687a6a6c1d |
Admin UI: Add policies (#6968)
* add policies to UI, accessing filer directly * view, edit policies * add back buttons for "users" page * remove unused * fix ui dark mode when modal is closed * bucket view details button * fix browser buttons * filer action button works * clean up masters page * fix volume servers action buttons * fix collections page action button * fix properties page * more obvious * fix directory creation file mode * Update file_browser_handlers.go * directory permission |
||
|
|
6b706f9ccd |
rename files
*_server.go - main server files *_management.go - business logic *_data.go - data structures and types *_middleware.go - middleware logic |