graph: Remove some uneeded stuff for the education backend

We don't need to support any complex queries on /education (yet?). And if we would need
to add support for $search, $filter, $expand or $select we should pass the parsed odata Query
instead of the raw url.Values struct.
This commit is contained in:
Ralf Haferkamp
2023-02-08 14:25:55 +01:00
committed by Ralf Haferkamp
parent 3a61f8c919
commit 25d2a2bc71
13 changed files with 81 additions and 252 deletions
@@ -32,7 +32,7 @@ func (g Graph) GetEducationClasses(w http.ResponseWriter, r *http.Request) {
return
}
classes, err := g.identityEducationBackend.GetEducationClasses(r.Context(), r.URL.Query())
classes, err := g.identityEducationBackend.GetEducationClasses(r.Context())
if err != nil {
logger.Debug().Err(err).Msg("could not get classes: backend error")
var errcode errorcode.Error
@@ -226,7 +226,7 @@ func (g Graph) GetEducationClass(w http.ResponseWriter, r *http.Request) {
Str("id", classID).
Interface("query", r.URL.Query()).
Msg("calling get class on backend")
class, err := g.identityEducationBackend.GetEducationClass(r.Context(), classID, r.URL.Query())
class, err := g.identityEducationBackend.GetEducationClass(r.Context(), classID)
if err != nil {
logger.Debug().Err(err).Msg("could not get class: backend error")
var errcode errorcode.Error
@@ -30,7 +30,7 @@ func (g Graph) GetEducationSchools(w http.ResponseWriter, r *http.Request) {
return
}
schools, err := g.identityEducationBackend.GetEducationSchools(r.Context(), r.URL.Query())
schools, err := g.identityEducationBackend.GetEducationSchools(r.Context())
if err != nil {
logger.Debug().Err(err).Msg("could not get schools: backend error")
var errcode errorcode.Error
@@ -170,7 +170,7 @@ func (g Graph) GetEducationSchool(w http.ResponseWriter, r *http.Request) {
Str("id", schoolID).
Interface("query", r.URL.Query()).
Msg("calling get school on backend")
school, err := g.identityEducationBackend.GetEducationSchool(r.Context(), schoolID, r.URL.Query())
school, err := g.identityEducationBackend.GetEducationSchool(r.Context(), schoolID)
if err != nil {
logger.Debug().Err(err).Msg("could not get school: backend error")
var errcode errorcode.Error
+3 -65
View File
@@ -10,11 +10,9 @@ import (
"strings"
"github.com/CiscoM31/godata"
cs3rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
revactx "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
@@ -22,7 +20,6 @@ import (
settings "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
settingssvc "github.com/owncloud/ocis/v2/services/settings/pkg/service/v0"
"golang.org/x/exp/slices"
)
// GetEducationUsers implements the Service interface.
@@ -38,7 +35,7 @@ func (g Graph) GetEducationUsers(w http.ResponseWriter, r *http.Request) {
}
logger.Debug().Interface("query", r.URL.Query()).Msg("calling get education users on backend")
users, err := g.identityEducationBackend.GetEducationUsers(r.Context(), r.URL.Query())
users, err := g.identityEducationBackend.GetEducationUsers(r.Context())
if err != nil {
logger.Debug().Err(err).Interface("query", r.URL.Query()).Msg("could not get education users from backend")
var errcode errorcode.Error
@@ -197,7 +194,7 @@ func (g Graph) GetEducationUser(w http.ResponseWriter, r *http.Request) {
}
logger.Debug().Str("id", userID).Msg("calling get education user from backend")
user, err := g.identityEducationBackend.GetEducationUser(r.Context(), userID, r.URL.Query())
user, err := g.identityEducationBackend.GetEducationUser(r.Context(), userID)
if err != nil {
logger.Debug().Err(err).Msg("could not get education user: error fetching education user from backend")
@@ -209,65 +206,6 @@ func (g Graph) GetEducationUser(w http.ResponseWriter, r *http.Request) {
}
return
}
sel := strings.Split(r.URL.Query().Get("$select"), ",")
exp := strings.Split(r.URL.Query().Get("$expand"), ",")
if slices.Contains(sel, "drive") || slices.Contains(sel, "drives") || slices.Contains(exp, "drive") || slices.Contains(exp, "drives") {
wdu, err := g.getWebDavBaseURL()
if err != nil {
// log error, wrong configuration
logger.Error().
Err(err).
Str("webdav_base", g.config.Spaces.WebDavBase).
Str("webdav_path", g.config.Spaces.WebDavPath).
Msg("error parsing webdav URL")
render.Status(r, http.StatusInternalServerError)
return
}
logger.Debug().Str("id", user.GetId()).Msg("calling list storage spaces with education user id filter")
f := listStorageSpacesUserFilter(user.GetId())
// use the unrestricted flag to get all possible spaces
// users with the canListAllSpaces permission should see all spaces
opaque := utils.AppendPlainToOpaque(nil, "unrestricted", "T")
lspr, err := g.gatewayClient.ListStorageSpaces(r.Context(), &storageprovider.ListStorageSpacesRequest{
Opaque: opaque,
Filters: []*storageprovider.ListStorageSpacesRequest_Filter{f},
})
if err != nil {
// transport error, needs to be fixed by admin
logger.Error().Err(err).Interface("query", r.URL.Query()).Msg("error getting storages: transport error")
render.Status(r, http.StatusInternalServerError)
render.JSON(w, r, user)
return
}
if lspr.GetStatus().GetCode() != cs3rpc.Code_CODE_OK {
logger.Debug().Str("grpc", lspr.GetStatus().GetMessage()).Msg("could not get drive for education user")
// in case of NOT_OK, we can just return the user object with empty drives
render.Status(r, status.HTTPStatusFromCode(http.StatusOK))
render.JSON(w, r, user)
return
}
drives := []libregraph.Drive{}
for _, sp := range lspr.GetStorageSpaces() {
d, err := g.cs3StorageSpaceToDrive(r.Context(), wdu, sp)
if err != nil {
logger.Debug().Err(err).Interface("id", sp.Id).Msg("error converting space to drive")
continue
}
quota, err := g.getDriveQuota(r.Context(), sp)
if err != nil {
logger.Debug().Err(err).Interface("id", sp.Id).Msg("error calling get quota on drive")
}
d.Quota = &quota
if slices.Contains(sel, "drive") || slices.Contains(exp, "drive") {
if *d.DriveType == _spaceTypePersonal {
user.Drive = d
}
} else {
drives = append(drives, *d)
user.Drives = drives
}
}
}
render.Status(r, http.StatusOK)
render.JSON(w, r, user)
@@ -291,7 +229,7 @@ func (g Graph) DeleteEducationUser(w http.ResponseWriter, r *http.Request) {
return
}
logger.Debug().Str("id", userID).Msg("calling get education user on user backend")
user, err := g.identityEducationBackend.GetEducationUser(r.Context(), userID, r.URL.Query())
user, err := g.identityEducationBackend.GetEducationUser(r.Context(), userID)
if err != nil {
logger.Debug().Err(err).Str("userID", userID).Msg("failed to get education user from backend")
var errcode errorcode.Error
@@ -216,84 +216,8 @@ var _ = Describe("EducationUsers", func() {
err = json.Unmarshal(data, &responseUser)
Expect(err).ToNot(HaveOccurred())
Expect(responseUser.GetId()).To(Equal("user1"))
Expect(len(responseUser.GetDrives())).To(Equal(0))
})
It("includes the personal space if requested", func() {
user := &libregraph.EducationUser{}
user.SetId("user1")
identityEducationBackend.On("GetEducationUser", mock.Anything, mock.Anything, mock.Anything).Return(user, nil)
gatewayClient.On("GetQuota", mock.Anything, mock.Anything, mock.Anything).Return(&provider.GetQuotaResponse{
Status: status.NewOK(ctx),
TotalBytes: 10,
}, nil)
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything, mock.Anything).Return(&provider.ListStorageSpacesResponse{
Status: status.NewOK(ctx),
StorageSpaces: []*provider.StorageSpace{
{
Id: &provider.StorageSpaceId{OpaqueId: "drive1"},
Root: &provider.ResourceId{SpaceId: "space", OpaqueId: "space"},
SpaceType: "project",
},
{
Id: &provider.StorageSpaceId{OpaqueId: "personal"},
Root: &provider.ResourceId{SpaceId: "personal", OpaqueId: "personal"},
SpaceType: "personal",
},
},
}, nil)
r := httptest.NewRequest(http.MethodGet, "/graph/v1.0/education/users?$expand=drive", nil)
rctx := chi.NewRouteContext()
rctx.URLParams.Add("userID", *user.Id)
r = r.WithContext(context.WithValue(revactx.ContextSetUser(ctx, currentUser), chi.RouteCtxKey, rctx))
svc.GetEducationUser(rr, r)
Expect(rr.Code).To(Equal(http.StatusOK))
data, err := io.ReadAll(rr.Body)
Expect(err).ToNot(HaveOccurred())
responseUser := &libregraph.EducationUser{}
err = json.Unmarshal(data, &responseUser)
Expect(err).ToNot(HaveOccurred())
Expect(responseUser.GetId()).To(Equal("user1"))
Expect(*responseUser.GetDrive().Id).To(Equal("personal"))
})
It("includes the drives if requested", func() {
user := &libregraph.EducationUser{}
user.SetId("user1")
identityEducationBackend.On("GetEducationUser", mock.Anything, mock.Anything, mock.Anything).Return(user, nil)
gatewayClient.On("GetQuota", mock.Anything, mock.Anything, mock.Anything).Return(&provider.GetQuotaResponse{
Status: status.NewOK(ctx),
TotalBytes: 10,
}, nil)
gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything, mock.Anything).Return(&provider.ListStorageSpacesResponse{
Status: status.NewOK(ctx),
StorageSpaces: []*provider.StorageSpace{
{
Id: &provider.StorageSpaceId{OpaqueId: "drive1"},
Root: &provider.ResourceId{SpaceId: "space", OpaqueId: "space"},
},
},
}, nil)
r := httptest.NewRequest(http.MethodGet, "/graph/v1.0/education/users?$expand=drives", nil)
rctx := chi.NewRouteContext()
rctx.URLParams.Add("userID", *user.Id)
r = r.WithContext(context.WithValue(revactx.ContextSetUser(ctx, currentUser), chi.RouteCtxKey, rctx))
svc.GetEducationUser(rr, r)
Expect(rr.Code).To(Equal(http.StatusOK))
data, err := io.ReadAll(rr.Body)
Expect(err).ToNot(HaveOccurred())
responseUser := &libregraph.EducationUser{}
err = json.Unmarshal(data, &responseUser)
Expect(err).ToNot(HaveOccurred())
Expect(responseUser.GetId()).To(Equal("user1"))
Expect(len(responseUser.GetDrives())).To(Equal(1))
})
})
Describe("PostEducationUser", func() {