diff --git a/server/internal/api/api.go b/server/internal/api/api.go index 6de8ab4a..0cd30345 100644 --- a/server/internal/api/api.go +++ b/server/internal/api/api.go @@ -15,5 +15,5 @@ func Setup(r *gin.RouterGroup, a *core.App) { r.Use(auth.CreateApiAuthHandler(a)) routes.SetupResourceRoutes(r) routes.SetupUserRoutes(r) - routes.SetupMobileRoutes(r) + routes.SetupMyRoutes(r, a) } diff --git a/server/internal/api/routes/mobile.go b/server/internal/api/routes/mobile.go deleted file mode 100644 index 402c15a8..00000000 --- a/server/internal/api/routes/mobile.go +++ /dev/null @@ -1,36 +0,0 @@ -package routes - -import ( - iofs "io/fs" - - "github.com/gin-gonic/gin" - "github.com/shroff/phylum/server/internal/api/auth" - "github.com/shroff/phylum/server/internal/api/errors" -) - -type mobileHomeResponse struct { - User userResponse `json:"user"` - Home resourceDetailResponse `json:"home"` -} - -func SetupMobileRoutes(r *gin.RouterGroup) { - group := r.Group("/mobile") - group.GET("/home", handleMobileHomeRoute) -} - -func handleMobileHomeRoute(c *gin.Context) { - user := auth.GetUser(c) - fs := auth.GetFileSystem(c) - r, err := fs.ResourceByID(user.Home) - if err != nil { - if errors.Is(err, iofs.ErrNotExist) { - err = errResourceNotFound - } - panic(err) - } - - c.JSON(200, mobileHomeResponse{ - User: responseFromUser(user), - Home: detailedResponseFromResource(fs, r), - }) -} diff --git a/server/internal/api/routes/my.go b/server/internal/api/routes/my.go new file mode 100644 index 00000000..92b12319 --- /dev/null +++ b/server/internal/api/routes/my.go @@ -0,0 +1,58 @@ +package routes + +import ( + iofs "io/fs" + + "github.com/gin-gonic/gin" + "github.com/shroff/phylum/server/internal/api/auth" + "github.com/shroff/phylum/server/internal/api/errors" + "github.com/shroff/phylum/server/internal/core" +) + +type myHomeResponse struct { + User userResponse `json:"user"` + Home resourceDetailResponse `json:"home"` +} + +type mySharedResponse struct { + Shared []resourceResponse `json:"shared"` +} + +func SetupMyRoutes(r *gin.RouterGroup, a *core.App) { + group := r.Group("/my") + group.GET("/home", handleMyHomeRoute) + group.GET("/shared", createMySharedRouteHandler(a)) +} + +func handleMyHomeRoute(c *gin.Context) { + user := auth.GetUser(c) + fs := auth.GetFileSystem(c) + r, err := fs.ResourceByID(user.Home) + if err != nil { + if errors.Is(err, iofs.ErrNotExist) { + err = errResourceNotFound + } + panic(err) + } + + c.JSON(200, myHomeResponse{ + User: responseFromUser(user), + Home: detailedResponseFromResource(fs, r), + }) +} + +func createMySharedRouteHandler(a *core.App) func(*gin.Context) { + return func(c *gin.Context) { + user := auth.GetUser(c) + shared, err := a.GetSharedResources(c.Request.Context(), user) + if err != nil { + panic(err) + } + + result := make([]resourceResponse, len(shared)) + for i, r := range shared { + result[i] = responseFromResource(r) + } + c.JSON(200, mySharedResponse{Shared: result}) + } +} diff --git a/server/internal/core/app.go b/server/internal/core/app.go index f593b804..27d5aa5d 100644 --- a/server/internal/core/app.go +++ b/server/internal/core/app.go @@ -103,3 +103,25 @@ func (a *App) populateData(ctx context.Context) (user db.User, e error) { func (a App) OpenFileSystem(ctx context.Context, user User) FileSystem { return OpenFileSystem(a.db, ctx, a.cs, user.ID, user.Root) } + +func (a App) GetSharedResources(ctx context.Context, user User) (result []Resource, err error) { + res, err := a.db.Queries.SharedResources(ctx, db.SharedResourcesParams{UserID: user.ID, UserHome: user.Home}) + if err != nil { + return + } + + result = make([]Resource, len(res)) + for i, r := range res { + result[i] = resource{ + id: r.ID, + parentID: r.Parent, + name: r.Name, + size: r.Size.Int64, + collection: r.Dir, + modTime: r.Modified.Time, + sha256sum: r.Sha256sum.String, + permissions: r.Permissions, + } + } + return +} diff --git a/server/internal/db/resources.sql.go b/server/internal/db/resources.sql.go index 6d7f7e60..28710a8e 100644 --- a/server/internal/db/resources.sql.go +++ b/server/internal/db/resources.sql.go @@ -119,6 +119,46 @@ func (q *Queries) HardDeleteRecursive(ctx context.Context, id uuid.UUID) ([]uuid return items, nil } +const sharedResources = `-- name: SharedResources :many +SELECT id, parent, name, dir, created, modified, deleted, size, sha256sum, permissions FROM resources where permissions ? ($1::int)::text AND id <> $2::uuid +` + +type SharedResourcesParams struct { + UserID int32 + UserHome uuid.UUID +} + +func (q *Queries) SharedResources(ctx context.Context, arg SharedResourcesParams) ([]Resource, error) { + rows, err := q.db.Query(ctx, sharedResources, arg.UserID, arg.UserHome) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Resource + for rows.Next() { + var i Resource + if err := rows.Scan( + &i.ID, + &i.Parent, + &i.Name, + &i.Dir, + &i.Created, + &i.Modified, + &i.Deleted, + &i.Size, + &i.Sha256sum, + &i.Permissions, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const updateResourceContents = `-- name: UpdateResourceContents :exec UPDATE resources SET diff --git a/server/sql/queries/resources.sql b/server/sql/queries/resources.sql index b3ba5233..74e7b116 100644 --- a/server/sql/queries/resources.sql +++ b/server/sql/queries/resources.sql @@ -63,3 +63,6 @@ WITH RECURSIVE nodes(id, parent) AS ( DELETE FROM resources WHERE id in (SELECT id FROM nodes) RETURNING id; + +-- name: SharedResources :many +SELECT * FROM resources where permissions ? (@user_id::int)::text AND id <> @user_home::uuid AND deleted IS NULL; \ No newline at end of file