A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go

Setup linter #4

merged opened by cuducos.me targeting main from cuducos.me/at-container-registry: golangci-lint-setup

As discussed in PR #3, this PR starts working on the linting issue #4 little by little:

  • setting up the linter in the CI
  • (temporarily) configuring the linter to ignore packages not ready for linting yet
  • fixing issues reported on pkg/hold (choice here was 100% arbitrary, just to get started)
Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:3272gdrjsuikiff7qsgokgas/sh.tangled.repo.pull/3mbosefvnfz22
+56 -39
Interdiff #1 #2
.golangci.yml

This file has not been changed.

.tangled/workflows/lint.yaml

This file has not been changed.

+56 -39
pkg/auth/hold_remote.go
··· 324 324 } 325 325 326 326 // isCrewMemberNoCache queries XRPC without caching (internal helper) 327 + // Handles pagination to check all crew records, not just the first page 327 328 func (a *RemoteHoldAuthorizer) isCrewMemberNoCache(ctx context.Context, holdDID, userDID string) (bool, error) { 328 329 // Resolve DID to URL 329 330 holdURL := atproto.ResolveHoldURL(holdDID) 330 331 332 + // Paginate through all crew records 333 + cursor := "" 334 + for { 335 + // Build XRPC request URL with pagination 336 + // GET /xrpc/com.atproto.repo.listRecords?repo={did}&collection=io.atcr.hold.crew&limit=100 337 + xrpcURL := fmt.Sprintf("%s%s?repo=%s&collection=%s&limit=100", 338 + holdURL, atproto.RepoListRecords, url.QueryEscape(holdDID), url.QueryEscape(atproto.CrewCollection)) 339 + if cursor != "" { 340 + xrpcURL += "&cursor=" + url.QueryEscape(cursor) 341 + } 331 - // Build XRPC request URL 332 - // GET /xrpc/com.atproto.repo.listRecords?repo={did}&collection=io.atcr.hold.crew 333 - xrpcURL := fmt.Sprintf("%s%s?repo=%s&collection=%s", 334 - holdURL, atproto.RepoListRecords, url.QueryEscape(holdDID), url.QueryEscape(atproto.CrewCollection)) 335 342 343 + req, err := http.NewRequestWithContext(ctx, "GET", xrpcURL, nil) 344 + if err != nil { 345 + return false, err 346 + } 336 - req, err := http.NewRequestWithContext(ctx, "GET", xrpcURL, nil) 337 - if err != nil { 338 - return false, err 339 - } 340 347 348 + resp, err := a.httpClient.Do(req) 349 + if err != nil { 350 + return false, fmt.Errorf("XRPC request failed: %w", err) 351 + } 341 - resp, err := a.httpClient.Do(req) 342 - if err != nil { 343 - return false, fmt.Errorf("XRPC request failed: %w", err) 344 - } 345 - defer resp.Body.Close() 346 352 353 + if resp.StatusCode != http.StatusOK { 354 + body, _ := io.ReadAll(resp.Body) 355 + resp.Body.Close() 356 + return false, fmt.Errorf("XRPC request failed: status %d: %s", resp.StatusCode, string(body)) 357 + } 347 - if resp.StatusCode != http.StatusOK { 348 - body, _ := io.ReadAll(resp.Body) 349 - return false, fmt.Errorf("XRPC request failed: status %d: %s", resp.StatusCode, string(body)) 350 - } 351 358 359 + // Parse response 360 + var xrpcResp struct { 361 + Cursor string `json:"cursor"` 362 + Records []struct { 363 + URI string `json:"uri"` 364 + CID string `json:"cid"` 365 + Value struct { 366 + Type string `json:"$type"` 367 + Member string `json:"member"` 368 + Role string `json:"role"` 369 + Permissions []string `json:"permissions"` 370 + AddedAt string `json:"addedAt"` 371 + } `json:"value"` 372 + } `json:"records"` 373 + } 352 - // Parse response 353 - var xrpcResp struct { 354 - Records []struct { 355 - URI string `json:"uri"` 356 - CID string `json:"cid"` 357 - Value struct { 358 - Type string `json:"$type"` 359 - Member string `json:"member"` 360 - Role string `json:"role"` 361 - Permissions []string `json:"permissions"` 362 - AddedAt string `json:"addedAt"` 363 - } `json:"value"` 364 - } `json:"records"` 365 - } 366 374 375 + if err := json.NewDecoder(resp.Body).Decode(&xrpcResp); err != nil { 376 + resp.Body.Close() 377 + return false, fmt.Errorf("failed to decode XRPC response: %w", err) 378 + } 379 + resp.Body.Close() 367 - if err := json.NewDecoder(resp.Body).Decode(&xrpcResp); err != nil { 368 - return false, fmt.Errorf("failed to decode XRPC response: %w", err) 369 - } 370 380 381 + // Check if userDID is in this page of crew records 382 + for _, record := range xrpcResp.Records { 383 + if record.Value.Member == userDID { 384 + // TODO: Check expiration if set 385 + return true, nil 386 + } 371 - // Check if userDID is in the crew list 372 - for _, record := range xrpcResp.Records { 373 - if record.Value.Member == userDID { 374 - // TODO: Check expiration if set 375 - return true, nil 376 387 } 388 + 389 + // Check if there are more pages 390 + if xrpcResp.Cursor == "" || len(xrpcResp.Records) == 0 { 391 + break 392 + } 393 + cursor = xrpcResp.Cursor 377 394 } 378 395 379 396 return false, nil
pkg/hold/admin/admin.go

This file has not been changed.

pkg/hold/admin/handlers.go

This file has not been changed.

pkg/hold/admin/handlers_auth.go

This file has not been changed.

pkg/hold/admin/handlers_crew.go

This file has not been changed.

pkg/hold/pds/xrpc.go

This file has not been changed.

History

3 rounds 0 comments
sign up or login to add to the discussion
2 commits
expand
Implements linter for pkg/hold
Implements linter for pkg/hold missing warnings
expand 0 comments
pull request successfully merged
6 commits
expand
Implements linter for pkg/hold
fix bug creating layer records on non-tagged pushes
fix oauth scope mismatch
implement a basic crew management admin panel
fix oauth login on admin panel for production
Implements linter for pkg/hold missing warnings
expand 0 comments
1 commit
expand
Implements linter for pkg/hold
expand 0 comments