refactor: migrate Graph calls to libre-graph-api-go SDK (#13) - #24
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
|
Filed the two upstream
|
DeepDiver1975
left a comment
There was a problem hiding this comment.
Verdict: solid, behavior-preserving refactor with a real bug fix. Reviewed as a maintainer; verified against libre-graph-api-go source and the repo. Not approving/merging (review-only), but no blocking correctness issues found.
What I verified:
- SDK paths match the hand-rolled ones exactly. Server URL is
baseURL + "/graph"(graph.go:59) and the SDK templates resolve to the same routes the old code used:DrivesPermissionsApi.Invite->/v1beta1/drives/{d}/items/{i}/invite,DrivesRootApi.InviteSpaceRoot->/v1beta1/drives/{d}/root/invite,MeDriveApi.ListSharedByMe/WithMe->/v1beta1/me/drive/sharedByMe|sharedWithMe,DrivesApi.Get/Create/Update/DeleteDrive->/v1.0/drives. Version prefixes are preserved, as claimed. - Auth + 429 retry preserved:
graphTransport.RoundTripre-appliesapplyAuthand retries on 429 (graph.go:74-102). Body replay viaGetBodyclone is correct; bodyless requests fall through unchanged. - Invite envelope fix is real and correct.
NewDriveRecipient()in the SDK defaults@libre.graph.recipient.typeto"user"(model_drive_recipient.go), and the response isCollectionOfPermissions{Value}— so mappingresp.GetValue()ontoInviteOutput{Permissions}fixes the previously-empty list. The updated test assertingoutput.Permissions[0].ID == "p1"covers it. - The "kept hand-rolled" rationale checks out:
DriveUpdatehas no@UI.Hiddenfield, confirmingrestore_spacecan't migrate.
Notes (non-blocking):
sdkConvertrelies on SDK models and local structs sharing json tags. That holds for the fields these tools expose, but it's an implicit contract - a future SDK json-tag rename would silently drop a field rather than fail to compile. A short comment or a targeted test on one mapped struct (e.g. Drive) would harden it.- The
mainpseudo-version pin is the right call to flag. Agree with cutting a tagged libre-graph-api-go release and switching before this is depended on long-term. - Overlaps with the invite recipient-type fix in PR 26 (
handleInviteToSpace/handleUploadAndShare). This PR already fixes those two paths via the SDK default, so whichever merges second will need a rebase; PR 26's other three fixes are independent and still needed.
CI: Build & Test, Lint, and all three Snyk checks green.
🤖 Generated with Claude Code
|
PR #24 Review — refactor: migrate Graph calls to libre-graph-api-go SDK Overall verdict: Solid, behavior-preserving refactor with a genuine bug fix. The structural approach is sound. A few issues worth addressing before merge. Bug fix (verified correct) The {"value":[...]} envelope fix is real and confirmed by the updated tests. The old InviteOutput{Permissions:[...]} envelope assumption meant create_share and invite_to_space always returned empty permission lists on success. sdkConvert[]Permission → InviteOutput{Permissions: perms} fixes it Issues
Every tool handler calls c.GraphClient() which constructs a new &http.Client{...} and libregraph.NewAPIClient(cfg) per invocation. HTTP clients are designed to be shared — they carry connection pools. Creating one per call defeats connection reuse and leaks goroutines (each http.Client has its own idle-connection
The round-trip works today because SDK models and local structs share json tags for the fields the tools expose. But a future SDK json-tag rename silently drops the field rather than failing to compile. The existing test coverage partially mitigates this (e.g. output.Permissions[0].ID is asserted), but a Drive
default: If sdkConvert fails (a programming error, not a server error), permissions are silently omitted but the message says "space created with members". Pre-existing pattern from the old code, but now there's a new failure mode. At minimum, log or include the conversion error in the message.
Pinning libre-graph-api-go at a main pseudo-version is clearly the right pragmatic call (tagged releases lack the APIs needed). The PR acknowledges this. The upstream issues (#10, #11) are filed. This should block a stable v2.0 release but is fine for merging now. Minor
|
Part of #13. Adds the SDK dependency and an auth-aware SDK client (client.GraphClient(): a graphTransport reuses the existing http client's transport and re-applies auth + 429 retry, so the version prefixes and request shapes are maintained by the SDK instead of hand-rolled paths). shares.go: create/createLink/list/update/updateExpiration/delete/reject and sharedByMe/sharedWithMe now use DrivesPermissionsApi / MeDriveApi. SDK responses are mapped onto the existing tool output structs via sdkConvert (JSON round-trip) so the tool JSON contract is unchanged. This also fixes a latent bug: the /invite response envelope is {"value":[...]} (verified against oCIS 8.0.1), not the {"permissions":[...]} the hand-rolled InviteOutput parsed — so create_share previously returned an empty permission list even on success. Kept hand-rolled (not covered by the SDK): accept_share (no SDK method) and get_sharing_roles (SDK roleDefinitions return type is code-gen-broken — singular vs the live JSON array). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: David Walter <david.walter@kiteworks.com>
Part of #13. get/create/update/disable space now use DrivesApi; invite/ createLink/listPermissions on the space root use DrivesRootApi. SDK responses map onto the existing Drive/Permission output structs via sdkConvert. invite_to_space also gains the recipient-type fix (NewDriveRecipient defaults @libre.graph.recipient.type) and the {"value":[...]} envelope fix, matching create_share. Kept hand-rolled (not cleanly SDK-expressible): list_spaces / list_my_spaces (SDK list builders expose only $filter/$orderby, no $top/$skip — migrating would drop the tool's pagination), delete_space (needs the Purge:T header), restore_space (needs @UI.Hidden, absent from DriveUpdate), and the WebDAV space tools (empty_trashbin, set_space_image, set_space_readme). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: David Walter <david.walter@kiteworks.com>
…go SDK Part of #13. The Graph-backed steps now use the SDK: - upload_and_share: invite via DrivesPermissionsApi (+ recipient-type and {"value":[...]} envelope fix) - create_project_space: CreateDrive + InviteSpaceRoot - share_with_link: CreateLink - get_space_overview: GetDrive + ListPermissionsSpaceRoot The WebDAV steps (upload, propfind, search, download) stay hand-rolled — the SDK is Graph-only. find_and_download remains entirely WebDAV. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: David Walter <david.walter@kiteworks.com>
9dd4086 to
07ba4ac
Compare
Problem
Per #13, the server hand-rolls LibreGraph paths (
/graph/v1beta1/...) and response shapes, which drift from the API — the source of bugs like #11 (wrong version prefix) and the share-invite envelope bug below.What changed
libre-graph-api-goand an auth-aware SDK client —client.GraphClient(). AgraphTransportwraps the existing HTTP transport and re-applies the configured auth (app-token Basic / OIDC Bearer) and the 429-retry, so version prefixes and request/response shapes are maintained by the SDK.DrivesPermissionsApi/DrivesApi/DrivesRootApi/MeDriveApi.sdkConvert(a JSON round-trip), so each tool's JSON output contract is unchanged.Bug fixed along the way
The
/inviteresponse envelope is{"value":[...]}(verified against oCIS 8.0.1), not the{"permissions":[...]}the hand-rolledInviteOutputparsed — socreate_shareandinvite_to_spacepreviously returned an empty permission list even on a successful 200. The SDK'sCollectionOfPermissions{Value}fixes this.Kept hand-rolled (scoped — not covered by the SDK)
get_sharing_roles+sharing-rolesresourceroleDefinitionsreturn type is code-gen-broken (singular*UnifiedRoleDefinitionvs the live JSON array)accept_sharelist_spaces/list_my_spaces$filter/$orderby— no$top/$skip, so migrating would drop the tool's paginationdelete_space(purge)Purge: Trequest headerrestore_space@UI.Hidden, absent fromDriveUpdateThe internal
GetJSON/ListJSON/PostJSON/… helpers remain only for these scoped endpoints (and the not-yet-migrated tool files).The
drivesPermissions/activities/driveItemAPIs are not in any tagged SDK release (latestv1.0.4lacks them); they exist only on the SDK'smain. This PR therefore pinslibre-graph-api-goat amainpseudo-version (v1.0.5-0.20260528...). Recommend cutting alibre-graph-api-gorelease and switching to the tag. (Context on #13.)Testing
go build ./...,go test -race ./...,go vet ./...,golangci-lint run ./...all pass; coverage 74.4% (> 70%).{"value"}envelope fix now returns permissions.Refs #13