Skip to content

Commit dd7b4f7

Browse files
authored
Open notes and OO docs inside shared drives (#4557)
2 parents fe6d595 + e8f6ab1 commit dd7b4f7

5 files changed

Lines changed: 130 additions & 4 deletions

File tree

docs/shared-drives.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,3 +405,21 @@ Downloads an old version of the file content.
405405
Identical call to [`GET /files/download/:file-id/:version-id`](files.md#get-filesdownloadfile-idversion-id)
406406
but over a shared drive. See there for request and response examples, the only
407407
difference is the URL.
408+
409+
## Notes
410+
411+
### POST /sharings/drives/:id/notes
412+
413+
Create a note inside a shared drive. Identical to [`POST /notes`](notes.md#post-notes).
414+
415+
### GET /sharings/drives/:id/notes/:file-id/open
416+
417+
Return the parameters to build the URL where the note can be opened.
418+
Identical to [`GET /notes/:file-id/open`](notes.md#get-notesidopen).
419+
420+
## Office
421+
422+
### GET /sharings/drives/:id/office/:file-id/open
423+
424+
Returns the parameters to open an office document. Identical to
425+
[`GET /office/:file-id/open`](office.md#get-officeidopen).

web/notes/notes.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ func ForceNoteSync(c echo.Context) error {
322322
// parameters to build the URL where the note can be opened.
323323
func OpenNoteURL(c echo.Context) error {
324324
inst := middlewares.GetInstance(c)
325-
fileID := c.Param("id")
325+
fileID := c.Param("file-id")
326326
open, err := sharing.OpenNote(inst, fileID)
327327
if err != nil {
328328
return wrapError(err)
@@ -510,7 +510,7 @@ func Routes(router *echo.Group) {
510510
router.PUT("/:id/title", ChangeTitle)
511511
router.PUT("/:id/telepointer", PutTelepointer)
512512
router.POST("/:id/sync", ForceNoteSync)
513-
router.GET("/:id/open", OpenNoteURL)
513+
router.GET("/:file-id/open", OpenNoteURL)
514514
router.PUT("/:id/schema", UpdateNoteSchema)
515515
router.POST("/:id/images", UploadImage)
516516
router.POST("/:id/:image-id/copy", CopyImage)

web/office/office.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
// Open returns the parameters to open an office document.
2121
func Open(c echo.Context) error {
2222
inst := middlewares.GetInstance(c)
23-
fileID := c.Param("id")
23+
fileID := c.Param("file-id")
2424
open, err := sharing.OpenOffice(inst, fileID)
2525
if err != nil {
2626
return wrapError(err)
@@ -101,7 +101,7 @@ func Callback(c echo.Context) error {
101101

102102
// Routes sets the routing for the collaborative edition of office documents.
103103
func Routes(router *echo.Group) {
104-
router.GET("/:id/open", Open)
104+
router.GET("/:file-id/open", Open)
105105
router.POST("/keys/:key", FileByKey)
106106
router.POST("/callback", Callback)
107107
}

web/sharings/drives.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import (
1616
"github.com/cozy/cozy-stack/pkg/jsonapi"
1717
"github.com/cozy/cozy-stack/web/files"
1818
"github.com/cozy/cozy-stack/web/middlewares"
19+
"github.com/cozy/cozy-stack/web/notes"
20+
"github.com/cozy/cozy-stack/web/office"
1921
"github.com/labstack/echo/v4"
2022
)
2123

@@ -315,6 +317,22 @@ func FileDownloadHandler(c echo.Context, inst *instance.Instance, s *sharing.Sha
315317
return files.FileDownloadHandler(c)
316318
}
317319

320+
// CreateNote allows to create a note inside a shared drive.
321+
func CreateNote(c echo.Context, inst *instance.Instance, s *sharing.Sharing) error {
322+
return notes.CreateNote(c)
323+
}
324+
325+
// OpenNoteURL returns the parameters to open a note inside a shared drive.
326+
func OpenNoteURL(c echo.Context, inst *instance.Instance, s *sharing.Sharing) error {
327+
return notes.OpenNoteURL(c)
328+
}
329+
330+
// OpenOffice returns the parameter to open an office document inside a shared
331+
// drive.
332+
func OpenOffice(c echo.Context, inst *instance.Instance, s *sharing.Sharing) error {
333+
return office.Open(c)
334+
}
335+
318336
// Find the directory linked to the drive sharing and return it if the user
319337
// requesting it has the proper permissions.
320338
func getSharingDir(c echo.Context, inst *instance.Instance, s *sharing.Sharing) (*vfs.DirDoc, error) {
@@ -372,6 +390,10 @@ func drivesRoutes(router *echo.Group) {
372390
drive.DELETE("/trash/:file-id", proxy(DestroyFileHandler, true))
373391

374392
drive.DELETE("/:file-id", proxy(TrashHandler, true))
393+
394+
drive.POST("/notes", proxy(CreateNote, true))
395+
drive.GET("/notes/:file-id/open", proxy(OpenNoteURL, true))
396+
drive.GET("/office/:file-id/open", proxy(OpenOffice, true))
375397
}
376398

377399
func proxy(fn func(c echo.Context, inst *instance.Instance, s *sharing.Sharing) error, needsAuth bool) echo.HandlerFunc {

web/sharings/drives_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,4 +892,90 @@ func TestSharedDrives(t *testing.T) {
892892
res.Header("Content-Disposition").IsEqual(`attachment; filename="` + checklistName + `"`)
893893
})
894894
})
895+
896+
t.Run("CreateAndOpenNote", func(t *testing.T) {
897+
eA := httpexpect.Default(t, tsA.URL)
898+
eB := httpexpect.Default(t, tsB.URL)
899+
900+
t.Run("CreateNoteInSharedDrive", func(t *testing.T) {
901+
// Create a note in the shared drive as the owner
902+
obj := eA.POST("/sharings/drives/"+sharingID+"/notes").
903+
WithHeader("Authorization", "Bearer "+acmeAppToken).
904+
WithHeader("Content-Type", "application/json").
905+
WithBytes([]byte(`{
906+
"data": {
907+
"type": "io.cozy.notes.documents",
908+
"attributes": {
909+
"title": "Meeting Minutes",
910+
"dir_id": "` + meetingsID + `",
911+
"schema": {
912+
"nodes": [
913+
["doc", { "content": "block+" }],
914+
["paragraph", { "content": "inline*", "group": "block" }],
915+
["text", { "group": "inline" }],
916+
["bullet_list", { "content": "list_item+", "group": "block" }],
917+
["list_item", { "content": "paragraph block*" }]
918+
],
919+
"marks": [
920+
["em", {}],
921+
["strong", {}]
922+
],
923+
"topNode": "doc"
924+
}
925+
}
926+
}
927+
}`)).
928+
Expect().Status(201).
929+
JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}).
930+
Object()
931+
932+
data := obj.Value("data").Object()
933+
data.HasValue("type", "io.cozy.files")
934+
noteID := data.Value("id").String().NotEmpty().Raw()
935+
936+
attrs := data.Value("attributes").Object()
937+
attrs.HasValue("type", "file")
938+
attrs.HasValue("name", "Meeting Minutes.cozy-note")
939+
attrs.HasValue("mime", "text/vnd.cozy.note+markdown")
940+
941+
meta := attrs.Value("metadata").Object()
942+
meta.HasValue("title", "Meeting Minutes")
943+
meta.HasValue("version", 0)
944+
meta.Value("schema").Object().NotEmpty()
945+
meta.Value("content").Object().NotEmpty()
946+
947+
t.Run("OpenNoteFromSharedDrive", func(t *testing.T) {
948+
obj := eB.GET("/sharings/drives/"+sharingID+"/notes/"+noteID+"/open").
949+
WithHeader("Authorization", "Bearer "+bettyAppToken).
950+
Expect().Status(200).
951+
JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}).
952+
Object()
953+
954+
data := obj.Value("data").Object()
955+
data.HasValue("type", consts.NotesURL)
956+
data.HasValue("id", noteID)
957+
958+
attrs := data.Value("attributes").Object()
959+
attrs.HasValue("note_id", noteID)
960+
attrs.HasValue("subdomain", "nested")
961+
attrs.HasValue("instance", acmeInstance.Domain)
962+
attrs.Value("public_name").String().NotEmpty()
963+
})
964+
})
965+
966+
t.Run("CreateNoteWithoutAuthentication", func(t *testing.T) {
967+
eB.POST("/sharings/drives/"+sharingID+"/notes").
968+
WithHeader("Content-Type", "application/json").
969+
WithBytes([]byte(`{
970+
"data": {
971+
"type": "io.cozy.notes.documents",
972+
"attributes": {
973+
"title": "Unauthorized Note",
974+
"dir_id": "` + meetingsID + `"
975+
}
976+
}
977+
}`)).
978+
Expect().Status(401)
979+
})
980+
})
895981
}

0 commit comments

Comments
 (0)