code clean up

This commit is contained in:
Evan Jarrett
2025-10-11 23:29:56 -05:00
parent 256cc883c9
commit 0706132186
10 changed files with 105 additions and 112 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ import (
_ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
// Register our custom middleware
_ "atcr.io/pkg/middleware"
_ "atcr.io/pkg/appview/middleware"
)
func main() {
+12 -13
View File
@@ -19,16 +19,15 @@ import (
sqlite3 "github.com/mattn/go-sqlite3"
"github.com/spf13/cobra"
"atcr.io/pkg/appview/middleware"
"atcr.io/pkg/auth/oauth"
"atcr.io/pkg/auth/token"
"atcr.io/pkg/middleware"
// UI components
"atcr.io/pkg/appview"
"atcr.io/pkg/appview/db"
uihandlers "atcr.io/pkg/appview/handlers"
"atcr.io/pkg/appview/jetstream"
appmiddleware "atcr.io/pkg/appview/middleware"
"github.com/gorilla/mux"
)
@@ -474,7 +473,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
// Public routes (with optional auth for navbar)
// SECURITY: Public pages use read-only DB
router.Handle("/", appmiddleware.OptionalAuth(sessionStore, database)(
router.Handle("/", middleware.OptionalAuth(sessionStore, database)(
&uihandlers.HomeHandler{
DB: readOnlyDB,
Templates: templates,
@@ -482,7 +481,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
},
)).Methods("GET")
router.Handle("/api/recent-pushes", appmiddleware.OptionalAuth(sessionStore, database)(
router.Handle("/api/recent-pushes", middleware.OptionalAuth(sessionStore, database)(
&uihandlers.RecentPushesHandler{
DB: readOnlyDB,
Templates: templates,
@@ -491,7 +490,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
)).Methods("GET")
// SECURITY: Search uses read-only DB to prevent writes and limit access to sensitive tables
router.Handle("/search", appmiddleware.OptionalAuth(sessionStore, database)(
router.Handle("/search", middleware.OptionalAuth(sessionStore, database)(
&uihandlers.SearchHandler{
DB: readOnlyDB,
Templates: templates,
@@ -499,7 +498,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
},
)).Methods("GET")
router.Handle("/api/search-results", appmiddleware.OptionalAuth(sessionStore, database)(
router.Handle("/api/search-results", middleware.OptionalAuth(sessionStore, database)(
&uihandlers.SearchResultsHandler{
DB: readOnlyDB,
Templates: templates,
@@ -508,7 +507,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
)).Methods("GET")
// API route for repository stats (public, read-only)
router.Handle("/api/stats/{handle}/{repository}", appmiddleware.OptionalAuth(sessionStore, database)(
router.Handle("/api/stats/{handle}/{repository}", middleware.OptionalAuth(sessionStore, database)(
&uihandlers.GetStatsHandler{
DB: readOnlyDB,
Directory: oauthApp.Directory(),
@@ -516,7 +515,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
)).Methods("GET")
// API routes for stars (require authentication)
router.Handle("/api/stars/{handle}/{repository}", appmiddleware.RequireAuth(sessionStore, database)(
router.Handle("/api/stars/{handle}/{repository}", middleware.RequireAuth(sessionStore, database)(
&uihandlers.StarRepositoryHandler{
DB: database, // Needs write access
Directory: oauthApp.Directory(),
@@ -524,7 +523,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
},
)).Methods("POST")
router.Handle("/api/stars/{handle}/{repository}", appmiddleware.RequireAuth(sessionStore, database)(
router.Handle("/api/stars/{handle}/{repository}", middleware.RequireAuth(sessionStore, database)(
&uihandlers.UnstarRepositoryHandler{
DB: database, // Needs write access
Directory: oauthApp.Directory(),
@@ -532,7 +531,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
},
)).Methods("DELETE")
router.Handle("/api/stars/{handle}/{repository}", appmiddleware.OptionalAuth(sessionStore, database)(
router.Handle("/api/stars/{handle}/{repository}", middleware.OptionalAuth(sessionStore, database)(
&uihandlers.CheckStarHandler{
DB: readOnlyDB, // Read-only check
Directory: oauthApp.Directory(),
@@ -540,7 +539,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
},
)).Methods("GET")
router.Handle("/u/{handle}", appmiddleware.OptionalAuth(sessionStore, database)(
router.Handle("/u/{handle}", middleware.OptionalAuth(sessionStore, database)(
&uihandlers.UserPageHandler{
DB: readOnlyDB,
Templates: templates,
@@ -548,7 +547,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
},
)).Methods("GET")
router.Handle("/r/{handle}/{repository}", appmiddleware.OptionalAuth(sessionStore, database)(
router.Handle("/r/{handle}/{repository}", middleware.OptionalAuth(sessionStore, database)(
&uihandlers.RepositoryPageHandler{
DB: readOnlyDB,
Templates: templates,
@@ -560,7 +559,7 @@ func initializeUIRoutes(database *sql.DB, readOnlyDB *sql.DB, sessionStore *db.S
// Authenticated routes
authRouter := router.NewRoute().Subrouter()
authRouter.Use(appmiddleware.RequireAuth(sessionStore, database))
authRouter.Use(middleware.RequireAuth(sessionStore, database))
authRouter.Handle("/settings", &uihandlers.SettingsHandler{
Templates: templates,
@@ -14,10 +14,10 @@ import (
"github.com/distribution/distribution/v3/registry/storage/driver"
"github.com/distribution/reference"
"atcr.io/pkg/appview/storage"
"atcr.io/pkg/atproto"
"atcr.io/pkg/auth"
"atcr.io/pkg/auth/oauth"
"atcr.io/pkg/storage"
)
// Global refresher instance (set by main.go)
+7
View File
@@ -5,6 +5,13 @@ import (
"strings"
)
// AccessEntry represents access permissions for a resource
type AccessEntry struct {
Type string `json:"type"` // "repository"
Name string `json:"name,omitempty"` // e.g., "alice/myapp"
Actions []string `json:"actions,omitempty"` // e.g., ["pull", "push"]
}
// ParseScope parses Docker registry scope strings into AccessEntry structures
// Scope format: "repository:alice/myapp:pull,push"
// Multiple scopes can be provided
-8
View File
@@ -1,8 +0,0 @@
package auth
// AccessEntry represents access permissions for a resource
type AccessEntry struct {
Type string `json:"type"` // "repository"
Name string `json:"name,omitempty"` // e.g., "alice/myapp"
Actions []string `json:"actions,omitempty"` // e.g., ["pull", "push"]
}
+84
View File
@@ -12,6 +12,29 @@ import (
"atcr.io/pkg/atproto"
)
// PresignedURLOperation defines the type of presigned URL operation
type PresignedURLOperation string
const (
OperationGet PresignedURLOperation = "GET"
OperationHead PresignedURLOperation = "HEAD"
OperationPut PresignedURLOperation = "PUT"
)
// PresignedURLRequest represents a request for a presigned URL (GET, HEAD, or PUT)
type PresignedURLRequest struct {
Operation PresignedURLOperation `json:"operation"`
DID string `json:"did"`
Digest string `json:"digest"`
Size int64 `json:"size,omitempty"` // Only required for PUT operations
}
// PresignedURLResponse contains the presigned URL
type PresignedURLResponse struct {
URL string `json:"url"`
ExpiresAt time.Time `json:"expires_at"`
}
// HandlePresignedURL handles presigned URL requests (GET, HEAD, or PUT)
// Operation type is specified in the request body
func (s *HoldService) HandlePresignedURL(w http.ResponseWriter, r *http.Request) {
@@ -232,6 +255,18 @@ func (s *HoldService) HandleProxyPut(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
}
// StartMultipartUploadRequest initiates a multipart upload
type StartMultipartUploadRequest struct {
DID string `json:"did"`
Digest string `json:"digest"`
}
// StartMultipartUploadResponse contains the multipart upload ID
type StartMultipartUploadResponse struct {
UploadID string `json:"upload_id"`
ExpiresAt time.Time `json:"expires_at"`
}
// HandleStartMultipart initiates a multipart upload
func (s *HoldService) HandleStartMultipart(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
@@ -276,6 +311,20 @@ func (s *HoldService) HandleStartMultipart(w http.ResponseWriter, r *http.Reques
json.NewEncoder(w).Encode(resp)
}
// GetPartURLRequest requests a presigned URL for a specific part
type GetPartURLRequest struct {
DID string `json:"did"`
Digest string `json:"digest"`
UploadID string `json:"upload_id"`
PartNumber int `json:"part_number"`
}
// GetPartURLResponse contains the presigned URL for a part
type GetPartURLResponse struct {
URL string `json:"url"`
ExpiresAt time.Time `json:"expires_at"`
}
// HandleGetPartURL generates a presigned URL for uploading a specific part
func (s *HoldService) HandleGetPartURL(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
@@ -325,6 +374,20 @@ func (s *HoldService) HandleGetPartURL(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(resp)
}
// CompleteMultipartRequest completes a multipart upload
type CompleteMultipartRequest struct {
DID string `json:"did"`
Digest string `json:"digest"`
UploadID string `json:"upload_id"`
Parts []CompletedPart `json:"parts"`
}
// CompletedPart represents an uploaded part with its ETag
type CompletedPart struct {
PartNumber int `json:"part_number"`
ETag string `json:"etag"`
}
// HandleCompleteMultipart completes a multipart upload
func (s *HoldService) HandleCompleteMultipart(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
@@ -381,6 +444,13 @@ func (s *HoldService) HandleCompleteMultipart(w http.ResponseWriter, r *http.Req
})
}
// AbortMultipartRequest aborts an in-progress upload
type AbortMultipartRequest struct {
DID string `json:"did"`
Digest string `json:"digest"`
UploadID string `json:"upload_id"`
}
// HandleAbortMultipart aborts an in-progress multipart upload
func (s *HoldService) HandleAbortMultipart(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
@@ -427,6 +497,20 @@ func (s *HoldService) HandleAbortMultipart(w http.ResponseWriter, r *http.Reques
})
}
// RegisterRequest represents a request to register this hold in a user's PDS
type RegisterRequest struct {
DID string `json:"did"`
AccessToken string `json:"access_token"`
PDSEndpoint string `json:"pds_endpoint"`
}
// RegisterResponse contains the registration result
type RegisterResponse struct {
HoldURI string `json:"hold_uri"`
CrewURI string `json:"crew_uri"`
Message string `json:"message"`
}
// HandleRegister registers this hold service in a user's PDS (manual endpoint)
func (s *HoldService) HandleRegister(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
-89
View File
@@ -1,89 +0,0 @@
package hold
import (
"time"
)
// PresignedURLOperation defines the type of presigned URL operation
type PresignedURLOperation string
const (
OperationGet PresignedURLOperation = "GET"
OperationHead PresignedURLOperation = "HEAD"
OperationPut PresignedURLOperation = "PUT"
)
// PresignedURLRequest represents a request for a presigned URL (GET, HEAD, or PUT)
type PresignedURLRequest struct {
Operation PresignedURLOperation `json:"operation"`
DID string `json:"did"`
Digest string `json:"digest"`
Size int64 `json:"size,omitempty"` // Only required for PUT operations
}
// PresignedURLResponse contains the presigned URL
type PresignedURLResponse struct {
URL string `json:"url"`
ExpiresAt time.Time `json:"expires_at"`
}
// StartMultipartUploadRequest initiates a multipart upload
type StartMultipartUploadRequest struct {
DID string `json:"did"`
Digest string `json:"digest"`
}
// StartMultipartUploadResponse contains the multipart upload ID
type StartMultipartUploadResponse struct {
UploadID string `json:"upload_id"`
ExpiresAt time.Time `json:"expires_at"`
}
// GetPartURLRequest requests a presigned URL for a specific part
type GetPartURLRequest struct {
DID string `json:"did"`
Digest string `json:"digest"`
UploadID string `json:"upload_id"`
PartNumber int `json:"part_number"`
}
// GetPartURLResponse contains the presigned URL for a part
type GetPartURLResponse struct {
URL string `json:"url"`
ExpiresAt time.Time `json:"expires_at"`
}
// CompleteMultipartRequest completes a multipart upload
type CompleteMultipartRequest struct {
DID string `json:"did"`
Digest string `json:"digest"`
UploadID string `json:"upload_id"`
Parts []CompletedPart `json:"parts"`
}
// CompletedPart represents an uploaded part with its ETag
type CompletedPart struct {
PartNumber int `json:"part_number"`
ETag string `json:"etag"`
}
// AbortMultipartRequest aborts an in-progress upload
type AbortMultipartRequest struct {
DID string `json:"did"`
Digest string `json:"digest"`
UploadID string `json:"upload_id"`
}
// RegisterRequest represents a request to register this hold in a user's PDS
type RegisterRequest struct {
DID string `json:"did"`
AccessToken string `json:"access_token"`
PDSEndpoint string `json:"pds_endpoint"`
}
// RegisterResponse contains the registration result
type RegisterResponse struct {
HoldURI string `json:"hold_uri"`
CrewURI string `json:"crew_uri"`
Message string `json:"message"`
}