github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/web/files/permissions_test.go (about) 1 package files 2 3 import ( 4 "net/url" 5 "testing" 6 "time" 7 8 "github.com/cozy/cozy-stack/pkg/config/config" 9 "github.com/cozy/cozy-stack/pkg/consts" 10 "github.com/cozy/cozy-stack/tests/testutils" 11 "github.com/cozy/cozy-stack/web/errors" 12 "github.com/cozy/cozy-stack/web/middlewares" 13 "github.com/gavv/httpexpect/v2" 14 "github.com/labstack/echo/v4" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestPermissions(t *testing.T) { 19 if testing.Short() { 20 t.Skip("an instance is required for this test: test skipped due to the use of --short flag") 21 } 22 23 config.UseTestFile(t) 24 require.NoError(t, loadLocale(), "Could not load default locale translations") 25 26 testutils.NeedCouchdb(t) 27 setup := testutils.NewSetup(t, t.Name()) 28 29 config.GetConfig().Fs.URL = &url.URL{ 30 Scheme: "file", 31 Host: "localhost", 32 Path: t.TempDir(), 33 } 34 35 testInstance := setup.GetTestInstance() 36 client, token := setup.GetTestClient(consts.Files + " " + consts.CertifiedCarbonCopy + " " + consts.CertifiedElectronicSafe) 37 38 ts := setup.GetTestServer("/files", Routes, func(r *echo.Echo) *echo.Echo { 39 secure := middlewares.Secure(&middlewares.SecureConfig{ 40 CSPDefaultSrc: []middlewares.CSPSource{middlewares.CSPSrcSelf}, 41 CSPFrameAncestors: []middlewares.CSPSource{middlewares.CSPSrcNone}, 42 }) 43 r.Use(secure) 44 return r 45 }) 46 ts.Config.Handler.(*echo.Echo).HTTPErrorHandler = errors.ErrorHandler 47 t.Cleanup(ts.Close) 48 49 t.Run("CreateDirNoToken", func(t *testing.T) { 50 e := testutils.CreateTestClient(t, ts.URL) 51 52 // Missing the "Authorization" header 53 e.POST("/files/"). 54 WithQuery("Name", "foo"). 55 WithQuery("Type", "directory"). 56 Expect().Status(401) 57 }) 58 59 t.Run("CreateDirBadType", func(t *testing.T) { 60 e := testutils.CreateTestClient(t, ts.URL) 61 62 badtok, _ := testInstance.MakeJWT(consts.AccessTokenAudience, client.ClientID, "io.cozy.events", "", time.Now()) 63 64 e.POST("/files/"). 65 WithQuery("Name", "foo"). 66 WithQuery("Type", "directory"). 67 WithHeader("Authorization", "Bearer "+badtok). 68 Expect().Status(403) 69 }) 70 71 t.Run("CreateDirWildCard", func(t *testing.T) { 72 e := testutils.CreateTestClient(t, ts.URL) 73 74 wildTok, _ := testInstance.MakeJWT(consts.AccessTokenAudience, client.ClientID, "io.cozy.files.*", "", time.Now()) 75 76 e.POST("/files/"). 77 WithQuery("Name", "icancreateyou"). 78 WithQuery("Type", "directory"). 79 WithHeader("Authorization", "Bearer "+wildTok). 80 Expect().Status(201) 81 }) 82 83 t.Run("CreateDirLimitedScope", func(t *testing.T) { 84 e := testutils.CreateTestClient(t, ts.URL) 85 86 // Create dir "/permissionholder" 87 dirID := e.POST("/files/"). 88 WithQuery("Name", "permissionholder"). 89 WithQuery("Type", "directory"). 90 WithHeader("Authorization", "Bearer "+token). 91 Expect().Status(201). 92 JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}). 93 Object().Path("$.data.id").String().NotEmpty().Raw() 94 95 badtok, _ := testInstance.MakeJWT(consts.AccessTokenAudience, client.ClientID, "io.cozy.files:ALL:"+dirID, "", time.Now()) 96 97 // not in authorized dir 98 e.POST("/files/"). 99 WithQuery("Name", "icantcreateyou"). 100 WithQuery("Type", "directory"). 101 WithHeader("Authorization", "Bearer "+badtok). 102 Expect().Status(403) 103 104 // in authorized dir 105 e.POST("/files/"). 106 WithQuery("Name", "icantcreateyou"). 107 WithQuery("Type", "directory"). 108 WithHeader("Authorization", "Bearer "+token). 109 Expect().Status(201) 110 }) 111 112 t.Run("CreateDirBadVerb", func(t *testing.T) { 113 e := testutils.CreateTestClient(t, ts.URL) 114 115 badtok, _ := testInstance.MakeJWT(consts.AccessTokenAudience, client.ClientID, "io.cozy.files:GET", "", time.Now()) 116 117 e.POST("/files/"). 118 WithQuery("Name", "icantcreateyou"). 119 WithQuery("Type", "directory"). 120 WithHeader("Authorization", "Bearer "+badtok). 121 Expect().Status(403) 122 }) 123 }