Skip to content

Commit

Permalink
separate auth roles for downloading current FV and historic FVs (#187)
Browse files Browse the repository at this point in the history
* separate auth roles for downloading current FV and historic FVs
  • Loading branch information
drewda authored Oct 30, 2023
1 parent 32594ad commit fe22d56
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 17 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
PGPASSWORD: for_testing
PGHOST: localhost
PGPORT: 5432
TL_TEST_STORAGE: /tmp/tlserver
TL_TEST_SERVER_DATABASE_URL: postgres://root:for_testing@localhost:5432/tlv2_test_server?sslmode=disable
TL_DATABASE_URL: postgres://root:for_testing@localhost:5432/tlv2_test_server?sslmode=disable
services:
Expand Down
117 changes: 108 additions & 9 deletions server/rest/feed_version_download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

"github.com/interline-io/transitland-server/auth/ancheck"
"github.com/interline-io/transitland-server/auth/authn"
"github.com/interline-io/transitland-server/internal/testutil"
)

Expand All @@ -21,31 +22,89 @@ func TestFeedVersionDownloadRequest(t *testing.T) {
if err != nil {
t.Fatal(err)
}
restSrv = ancheck.AdminDefaultMiddleware("test")(restSrv)

t.Run("ok", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feed_versions/d2813c293bcfd7a97dde599527ae6c62c98e66c6/download", nil)
rr := httptest.NewRecorder()
restSrv.ServeHTTP(rr, req)
asAdmin := ancheck.AdminDefaultMiddleware("test")(restSrv)
asAdmin.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 200 {
t.Errorf("got status code %d, expected 200", sc)
}
if sc := len(rr.Body.Bytes()); sc != 59324 {
t.Errorf("got %d bytes, expected 59324", sc)
}
})
t.Run("not authorized", func(t *testing.T) {
t.Run("not authorized as anon", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feed_versions/d2813c293bcfd7a97dde599527ae6c62c98e66c6/download", nil)
rr := httptest.NewRecorder()
asAnon := restSrv
asAnon.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 401 {
t.Errorf("got status code %d, expected 401", sc)
}
})
t.Run("not authorized as user, missing role", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feed_versions/d2813c293bcfd7a97dde599527ae6c62c98e66c6/download", nil)
rr := httptest.NewRecorder()
asUser := ancheck.NewUserDefaultMiddleware(func() authn.User {
return authn.NewCtxUser("testuser", "", "").WithRoles("testrole")
})(restSrv)
asUser.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 401 {
t.Errorf("got status code %d, expected 401", sc)
}
})
t.Run("not authorized as user, only current download role", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feed_versions/d2813c293bcfd7a97dde599527ae6c62c98e66c6/download", nil)
rr := httptest.NewRecorder()
asUser := ancheck.NewUserDefaultMiddleware(func() authn.User {
return authn.NewCtxUser("testuser", "", "").WithRoles("tl_download_fv_current")
})(restSrv)
asUser.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 401 {
t.Errorf("got status code %d, expected 401", sc)
}
})
t.Run("authorized as user", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feed_versions/d2813c293bcfd7a97dde599527ae6c62c98e66c6/download", nil)
rr := httptest.NewRecorder()
asUser := ancheck.NewUserDefaultMiddleware(func() authn.User {
return authn.NewCtxUser("testuser", "", "").WithRoles("tl_download_fv_historic")
})(restSrv)
asUser.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 200 {
t.Errorf("got status code %d, expected 200", sc)
}
if sc := len(rr.Body.Bytes()); sc != 59324 {
t.Errorf("got %d bytes, expected 59324", sc)
}
})
t.Run("not authorized as anon, not redistributable", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feed_versions/dd7aca4a8e4c90908fd3603c097fabee75fea907/download", nil)
rr := httptest.NewRecorder()
restSrv.ServeHTTP(rr, req)
asAnon := restSrv
asAnon.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 401 {
t.Errorf("got status code %d, expected 401", sc)
}
})
t.Run("not authorized as user, not redistributable", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feed_versions/dd7aca4a8e4c90908fd3603c097fabee75fea907/download", nil)
rr := httptest.NewRecorder()
asUser := ancheck.NewUserDefaultMiddleware(func() authn.User {
return authn.NewCtxUser("testuser", "", "").WithRoles("tl_download_fv_historic")
})(restSrv)
asUser.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 401 {
t.Errorf("got status code %d, expected 401", sc)
}
})
t.Run("not found", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feed_versions/asdxyz/download", nil)
rr := httptest.NewRecorder()
restSrv.ServeHTTP(rr, req)
asAdmin := ancheck.AdminDefaultMiddleware("test")(restSrv)
asAdmin.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 404 {
t.Errorf("got status code %d, expected 404", sc)
}
Expand All @@ -68,26 +127,66 @@ func TestFeedDownloadLatestRequest(t *testing.T) {
t.Run("ok", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feeds/CT/download_latest_feed_version", nil)
rr := httptest.NewRecorder()
restSrv.ServeHTTP(rr, req)
asAdmin := ancheck.AdminDefaultMiddleware("test")(restSrv)
asAdmin.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 200 {
t.Errorf("got status code %d, expected 200", sc)
}
if sc := len(rr.Body.Bytes()); sc != 59324 {
t.Errorf("got %d bytes, expected 59324", sc)
}
})
t.Run("ok as user", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feeds/CT/download_latest_feed_version", nil)
rr := httptest.NewRecorder()
asUser := ancheck.NewUserDefaultMiddleware(func() authn.User {
return authn.NewCtxUser("testuser", "", "").WithRoles("tl_download_fv_current")
})(restSrv)
asUser.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 200 {
t.Errorf("got status code %d, expected 200", sc)
}
if sc := len(rr.Body.Bytes()); sc != 59324 {
t.Errorf("got %d bytes, expected 59324", sc)
}
})
t.Run("not authorized", func(t *testing.T) {
t.Run("not authorized as anon", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feeds/CT/download_latest_feed_version", nil)
rr := httptest.NewRecorder()
asAnon := restSrv
asAnon.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 401 {
t.Errorf("got status code %d, expected 401", sc)
}
})
t.Run("not authorized as user, missing role", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feeds/CT/download_latest_feed_version", nil)
rr := httptest.NewRecorder()
asUser := ancheck.NewUserDefaultMiddleware(func() authn.User {
return authn.NewCtxUser("testuser", "", "").WithRoles("testrole")
})(restSrv)
asUser.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 401 {
t.Errorf("got status code %d, expected 401", sc)
}
})
t.Run("not authorized as user, not redistributable", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feeds/BA/download_latest_feed_version", nil)
rr := httptest.NewRecorder()
restSrv.ServeHTTP(rr, req)
asUser := ancheck.NewUserDefaultMiddleware(func() authn.User {
return authn.NewCtxUser("testuser", "", "").WithRoles("download_latest_feed_version")
})(restSrv)
asUser.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 401 {
t.Errorf("got status code %d, expected 401", sc)
}
})

t.Run("not found", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/feeds/asdxyz/download_latest_feed_version", nil)
rr := httptest.NewRecorder()
restSrv.ServeHTTP(rr, req)
asAdmin := ancheck.AdminDefaultMiddleware("test")(restSrv)
asAdmin.ServeHTTP(rr, req)
if sc := rr.Result().StatusCode; sc != 404 {
t.Errorf("got status code %d, expected 404", sc)
}
Expand Down
4 changes: 2 additions & 2 deletions server/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ func NewServer(cfg config.Config, srv http.Handler) (http.Handler, error) {
r.HandleFunc("/feeds", feedHandler)
r.HandleFunc("/feeds/{feed_key}.{format}", feedHandler)
r.HandleFunc("/feeds/{feed_key}", feedHandler)
r.HandleFunc("/feeds/{feed_key}/download_latest_feed_version", makeHandlerFunc(restcfg, "feedVersionDownloadLatest", feedVersionDownloadLatestHandler))
r.Handle("/feeds/{feed_key}/download_latest_feed_version", ancheck.RoleRequired("tl_download_fv_current")(makeHandlerFunc(restcfg, "feedVersionDownloadLatest", feedVersionDownloadLatestHandler)))

r.HandleFunc("/feed_versions.{format}", feedVersionHandler)
r.HandleFunc("/feed_versions", feedVersionHandler)
r.HandleFunc("/feed_versions/{feed_version_key}.{format}", feedVersionHandler)
r.HandleFunc("/feed_versions/{feed_version_key}", feedVersionHandler)
r.HandleFunc("/feeds/{feed_key}/feed_versions", feedVersionHandler)
r.Handle("/feed_versions/{feed_version_key}/download", ancheck.RoleRequired("tl_user_pro")(makeHandlerFunc(restcfg, "feedVersionDownload", feedVersionDownloadHandler)))
r.Handle("/feed_versions/{feed_version_key}/download", ancheck.RoleRequired("tl_download_fv_historic")(makeHandlerFunc(restcfg, "feedVersionDownload", feedVersionDownloadHandler)))

r.HandleFunc("/agencies.{format}", agencyHandler)
r.HandleFunc("/agencies", agencyHandler)
Expand Down
12 changes: 6 additions & 6 deletions test_setup.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#!/bin/bash
# Remove import files
rm *.zip
TL_TEST_STORAGE="${TL_TEST_STORAGE:-tmp}"
mkdir -p "${TL_TEST_STORAGE}"; rm ${TL_TEST_STORAGE}/*.zip
# export TL_LOG=debug
(cd cmd/tlserver && go install .)
tlserver sync -dburl="$TL_TEST_SERVER_DATABASE_URL" test/data/server/server-test.dmfr.json
# older data
tlserver fetch -dburl="$TL_TEST_SERVER_DATABASE_URL" -allow-local-fetch -feed-url=test/data/external/bart-old.zip BA # old data
tlserver import -dburl="$TL_TEST_SERVER_DATABASE_URL"
tlserver fetch -dburl="$TL_TEST_SERVER_DATABASE_URL" -storage="$TL_TEST_STORAGE" -allow-local-fetch -feed-url=test/data/external/bart-old.zip BA # old data
tlserver import -dburl="$TL_TEST_SERVER_DATABASE_URL" -storage="$TL_TEST_STORAGE"
# current data
tlserver fetch -dburl="$TL_TEST_SERVER_DATABASE_URL" -allow-local-fetch
tlserver import -dburl="$TL_TEST_SERVER_DATABASE_URL" -activate
tlserver fetch -dburl="$TL_TEST_SERVER_DATABASE_URL" -storage="$TL_TEST_STORAGE" -allow-local-fetch
tlserver import -dburl="$TL_TEST_SERVER_DATABASE_URL" -storage="$TL_TEST_STORAGE" -activate
# sync again
tlserver sync -dburl="$TL_TEST_SERVER_DATABASE_URL" test/data/server/server-test.dmfr.json
# supplemental data
psql -f test_supplement.pgsql
rm *.zip

0 comments on commit fe22d56

Please sign in to comment.