graph: Pass parsed odata request to the identity backend

In preparation for some more advanced queries pass the parse odata request
tVo the identity backend methods instead of the raw url.Values{}. This also
add some helpers for validating $expand and $search queries to reject
some unsupported queries.

Also remove support for `$select=memberOf` and `$select=drive|drives` queries
and stick to the technically correct `$expand=...`.
This commit is contained in:
Ralf Haferkamp
2023-02-07 15:10:23 +01:00
committed by Ralf Haferkamp
parent 25d2a2bc71
commit 26f7523ff8
8 changed files with 177 additions and 75 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"net/url"
"github.com/CiscoM31/godata"
cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
@@ -25,8 +26,8 @@ type Backend interface {
DeleteUser(ctx context.Context, nameOrID string) error
// UpdateUser applies changes to given user, identified by username or id
UpdateUser(ctx context.Context, nameOrID string, user libregraph.User) (*libregraph.User, error)
GetUser(ctx context.Context, nameOrID string, queryParam url.Values) (*libregraph.User, error)
GetUsers(ctx context.Context, queryParam url.Values) ([]*libregraph.User, error)
GetUser(ctx context.Context, nameOrID string, oreq *godata.GoDataRequest) (*libregraph.User, error)
GetUsers(ctx context.Context, oreq *godata.GoDataRequest) ([]*libregraph.User, error)
// CreateGroup creates the supplied group in the identity backend.
CreateGroup(ctx context.Context, group libregraph.Group) (*libregraph.Group, error)

View File

@@ -4,6 +4,7 @@ import (
"context"
"net/url"
"github.com/CiscoM31/godata"
cs3group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
cs3user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
cs3rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
@@ -39,7 +40,8 @@ func (i *CS3) UpdateUser(ctx context.Context, nameOrID string, user libregraph.U
return nil, errNotImplemented
}
func (i *CS3) GetUser(ctx context.Context, userID string, queryParam url.Values) (*libregraph.User, error) {
// GetUser implements the Backend Interface.
func (i *CS3) GetUser(ctx context.Context, userID string, _ *godata.GoDataRequest) (*libregraph.User, error) {
logger := i.Logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "cs3").Msg("GetUser")
client, err := pool.GetGatewayServiceClient(i.Config.Address, i.Config.GetRevaOptions()...)
@@ -67,7 +69,8 @@ func (i *CS3) GetUser(ctx context.Context, userID string, queryParam url.Values)
return CreateUserModelFromCS3(res.User), nil
}
func (i *CS3) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregraph.User, error) {
// GetUsers implements the Backend Interface.
func (i *CS3) GetUsers(ctx context.Context, oreq *godata.GoDataRequest) ([]*libregraph.User, error) {
logger := i.Logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "cs3").Msg("GetUsers")
client, err := pool.GetGatewayServiceClient(i.Config.Address, i.Config.GetRevaOptions()...)
@@ -76,9 +79,9 @@ func (i *CS3) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregrap
return nil, errorcode.New(errorcode.ServiceNotAvailable, err.Error())
}
search := queryParam.Get("search")
if search == "" {
search = queryParam.Get("$search")
search, err := GetSearchValues(oreq.Query)
if err != nil {
return nil, err
}
res, err := client.FindUsers(ctx, &cs3user.FindUsersRequest{
@@ -107,6 +110,7 @@ func (i *CS3) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregrap
return users, nil
}
// GetGroups implements the Backend Interface.
func (i *CS3) GetGroups(ctx context.Context, queryParam url.Values) ([]*libregraph.Group, error) {
logger := i.Logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "cs3").Msg("GetGroups")
@@ -153,6 +157,7 @@ func (i *CS3) CreateGroup(ctx context.Context, group libregraph.Group) (*libregr
return nil, errorcode.New(errorcode.NotSupported, "not implemented")
}
// GetGroup implements the Backend Interface.
func (i *CS3) GetGroup(ctx context.Context, groupID string, queryParam url.Values) (*libregraph.Group, error) {
logger := i.Logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "cs3").Msg("GetGroup")

View File

@@ -4,9 +4,8 @@ import (
"context"
"errors"
"fmt"
"net/url"
"strings"
"github.com/CiscoM31/godata"
"github.com/go-ldap/ldap/v3"
"github.com/gofrs/uuid"
libregraph "github.com/owncloud/libre-graph-api-go"
@@ -369,20 +368,27 @@ func (i *LDAP) getLDAPUserByFilter(filter string) (*ldap.Entry, error) {
return i.searchLDAPEntryByFilter(i.userBaseDN, attrs, filter)
}
func (i *LDAP) GetUser(ctx context.Context, nameOrID string, queryParam url.Values) (*libregraph.User, error) {
// GetUser implements the Backend Interface.
func (i *LDAP) GetUser(ctx context.Context, nameOrID string, oreq *godata.GoDataRequest) (*libregraph.User, error) {
logger := i.logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "ldap").Msg("GetUser")
e, err := i.getLDAPUserByNameOrID(nameOrID)
if err != nil {
return nil, err
}
u := i.createUserModelFromLDAP(e)
if u == nil {
return nil, ErrNotFound
}
sel := strings.Split(queryParam.Get("$select"), ",")
exp := strings.Split(queryParam.Get("$expand"), ",")
if slices.Contains(sel, "memberOf") || slices.Contains(exp, "memberOf") {
exp, err := GetExpandValues(oreq.Query)
if err != nil {
return nil, err
}
if slices.Contains(exp, "memberOf") {
userGroups, err := i.getGroupsForUser(e.DN)
if err != nil {
return nil, err
@@ -392,14 +398,21 @@ func (i *LDAP) GetUser(ctx context.Context, nameOrID string, queryParam url.Valu
return u, nil
}
func (i *LDAP) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregraph.User, error) {
// GetUsers implements the Backend Interface.
func (i *LDAP) GetUsers(ctx context.Context, oreq *godata.GoDataRequest) ([]*libregraph.User, error) {
logger := i.logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "ldap").Msg("GetUsers")
search := queryParam.Get("search")
if search == "" {
search = queryParam.Get("$search")
search, err := GetSearchValues(oreq.Query)
if err != nil {
return nil, err
}
exp, err := GetExpandValues(oreq.Query)
if err != nil {
return nil, err
}
var userFilter string
if search != "" {
search = ldap.EscapeFilter(search)
@@ -439,14 +452,12 @@ func (i *LDAP) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregra
users := make([]*libregraph.User, 0, len(res.Entries))
for _, e := range res.Entries {
sel := strings.Split(queryParam.Get("$select"), ",")
exp := strings.Split(queryParam.Get("$expand"), ",")
u := i.createUserModelFromLDAP(e)
// Skip invalid LDAP users
if u == nil {
continue
}
if slices.Contains(sel, "memberOf") || slices.Contains(exp, "memberOf") {
if slices.Contains(exp, "memberOf") {
userGroups, err := i.getGroupsForUser(e.DN)
if err != nil {
return nil, err

View File

@@ -7,6 +7,7 @@ import (
"net/url"
"testing"
"github.com/CiscoM31/godata"
"github.com/go-ldap/ldap/v3"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
@@ -172,23 +173,24 @@ func TestGetUser(t *testing.T) {
nil, ldap.NewError(ldap.LDAPResultSizeLimitExceeded, errors.New("mock")))
b, _ := getMockedBackend(lm, lconfig, &logger)
queryParamExpand := url.Values{
"$expand": []string{"memberOf"},
odataReqDefault, err := godata.ParseRequest(context.Background(), "",
url.Values{})
if err != nil {
t.Errorf("Expected success got '%s'", err.Error())
}
queryParamSelect := url.Values{
"$select": []string{"memberOf"},
odataReqExpand, err := godata.ParseRequest(context.Background(), "",
url.Values{"$expand": []string{"memberOf"}})
if err != nil {
t.Errorf("Expected success got '%s'", err.Error())
}
_, err := b.GetUser(context.Background(), "fred", nil)
_, err = b.GetUser(context.Background(), "fred", odataReqDefault)
if err == nil || err.Error() != "itemNotFound" {
t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
}
_, err = b.GetUser(context.Background(), "fred", queryParamExpand)
if err == nil || err.Error() != "itemNotFound" {
t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
}
_, err = b.GetUser(context.Background(), "fred", queryParamSelect)
_, err = b.GetUser(context.Background(), "fred", odataReqExpand)
if err == nil || err.Error() != "itemNotFound" {
t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
}
@@ -199,17 +201,12 @@ func TestGetUser(t *testing.T) {
Return(
&ldap.SearchResult{}, nil)
b, _ = getMockedBackend(lm, lconfig, &logger)
_, err = b.GetUser(context.Background(), "fred", nil)
_, err = b.GetUser(context.Background(), "fred", odataReqDefault)
if err == nil || err.Error() != "itemNotFound" {
t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
}
_, err = b.GetUser(context.Background(), "fred", queryParamExpand)
if err == nil || err.Error() != "itemNotFound" {
t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
}
_, err = b.GetUser(context.Background(), "fred", queryParamSelect)
_, err = b.GetUser(context.Background(), "fred", odataReqExpand)
if err == nil || err.Error() != "itemNotFound" {
t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
}
@@ -224,21 +221,14 @@ func TestGetUser(t *testing.T) {
nil)
b, _ = getMockedBackend(lm, lconfig, &logger)
u, err := b.GetUser(context.Background(), "user", nil)
u, err := b.GetUser(context.Background(), "user", odataReqDefault)
if err != nil {
t.Errorf("Expected GetUser to succeed. Got %s", err.Error())
} else if *u.Id != userEntry.GetEqualFoldAttributeValue(b.userAttributeMap.id) {
t.Errorf("Expected GetUser to return a valid user")
}
u, err = b.GetUser(context.Background(), "user", queryParamExpand)
if err != nil {
t.Errorf("Expected GetUser to succeed. Got %s", err.Error())
} else if *u.Id != userEntry.GetEqualFoldAttributeValue(b.userAttributeMap.id) {
t.Errorf("Expected GetUser to return a valid user")
}
u, err = b.GetUser(context.Background(), "user", queryParamSelect)
u, err = b.GetUser(context.Background(), "user", odataReqExpand)
if err != nil {
t.Errorf("Expected GetUser to succeed. Got %s", err.Error())
} else if *u.Id != userEntry.GetEqualFoldAttributeValue(b.userAttributeMap.id) {
@@ -266,8 +256,14 @@ func TestGetUsers(t *testing.T) {
lm := &mocks.Client{}
lm.On("Search", mock.Anything).Return(nil, ldap.NewError(ldap.LDAPResultOperationsError, errors.New("mock")))
odataReqDefault, err := godata.ParseRequest(context.Background(), "",
url.Values{})
if err != nil {
t.Errorf("Expected success got '%s'", err.Error())
}
b, _ := getMockedBackend(lm, lconfig, &logger)
_, err := b.GetUsers(context.Background(), url.Values{})
_, err = b.GetUsers(context.Background(), odataReqDefault)
if err == nil || err.Error() != "itemNotFound" {
t.Errorf("Expected 'itemNotFound' got '%s'", err.Error())
}
@@ -275,7 +271,7 @@ func TestGetUsers(t *testing.T) {
lm = &mocks.Client{}
lm.On("Search", mock.Anything).Return(&ldap.SearchResult{}, nil)
b, _ = getMockedBackend(lm, lconfig, &logger)
g, err := b.GetUsers(context.Background(), url.Values{})
g, err := b.GetUsers(context.Background(), odataReqDefault)
if err != nil {
t.Errorf("Expected success, got '%s'", err.Error())
} else if g == nil || len(g) != 0 {

View File

@@ -5,6 +5,8 @@ package mocks
import (
context "context"
godata "github.com/CiscoM31/godata"
libregraph "github.com/owncloud/libre-graph-api-go"
mock "github.com/stretchr/testify/mock"
@@ -174,13 +176,13 @@ func (_m *Backend) GetGroups(ctx context.Context, queryParam url.Values) ([]*lib
return r0, r1
}
// GetUser provides a mock function with given fields: ctx, nameOrID, queryParam
func (_m *Backend) GetUser(ctx context.Context, nameOrID string, queryParam url.Values) (*libregraph.User, error) {
ret := _m.Called(ctx, nameOrID, queryParam)
// GetUser provides a mock function with given fields: ctx, nameOrID, oreq
func (_m *Backend) GetUser(ctx context.Context, nameOrID string, oreq *godata.GoDataRequest) (*libregraph.User, error) {
ret := _m.Called(ctx, nameOrID, oreq)
var r0 *libregraph.User
if rf, ok := ret.Get(0).(func(context.Context, string, url.Values) *libregraph.User); ok {
r0 = rf(ctx, nameOrID, queryParam)
if rf, ok := ret.Get(0).(func(context.Context, string, *godata.GoDataRequest) *libregraph.User); ok {
r0 = rf(ctx, nameOrID, oreq)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*libregraph.User)
@@ -188,8 +190,8 @@ func (_m *Backend) GetUser(ctx context.Context, nameOrID string, queryParam url.
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, string, url.Values) error); ok {
r1 = rf(ctx, nameOrID, queryParam)
if rf, ok := ret.Get(1).(func(context.Context, string, *godata.GoDataRequest) error); ok {
r1 = rf(ctx, nameOrID, oreq)
} else {
r1 = ret.Error(1)
}
@@ -197,13 +199,13 @@ func (_m *Backend) GetUser(ctx context.Context, nameOrID string, queryParam url.
return r0, r1
}
// GetUsers provides a mock function with given fields: ctx, queryParam
func (_m *Backend) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregraph.User, error) {
ret := _m.Called(ctx, queryParam)
// GetUsers provides a mock function with given fields: ctx, oreq
func (_m *Backend) GetUsers(ctx context.Context, oreq *godata.GoDataRequest) ([]*libregraph.User, error) {
ret := _m.Called(ctx, oreq)
var r0 []*libregraph.User
if rf, ok := ret.Get(0).(func(context.Context, url.Values) []*libregraph.User); ok {
r0 = rf(ctx, queryParam)
if rf, ok := ret.Get(0).(func(context.Context, *godata.GoDataRequest) []*libregraph.User); ok {
r0 = rf(ctx, oreq)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*libregraph.User)
@@ -211,8 +213,8 @@ func (_m *Backend) GetUsers(ctx context.Context, queryParam url.Values) ([]*libr
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, url.Values) error); ok {
r1 = rf(ctx, queryParam)
if rf, ok := ret.Get(1).(func(context.Context, *godata.GoDataRequest) error); ok {
r1 = rf(ctx, oreq)
} else {
r1 = ret.Error(1)
}

View File

@@ -0,0 +1,41 @@
package identity
import "github.com/CiscoM31/godata"
// GetExpandValues extracts the values of the $expand query parameter and
// returns them in a []string, rejects any $expand value that consists of more
// than just a single path segment
func GetExpandValues(req *godata.GoDataQuery) ([]string, error) {
if req == nil || req.Expand == nil {
return []string{}, nil
}
expand := make([]string, 0, len(req.Expand.ExpandItems))
for _, item := range req.Expand.ExpandItems {
if item.Filter != nil || item.At != nil || item.Search != nil ||
item.OrderBy != nil || item.Skip != nil || item.Top != nil ||
item.Select != nil || item.Compute != nil || item.Expand != nil ||
item.Levels != 0 {
return []string{}, godata.NotImplementedError("options for $expand not supported")
}
if len(item.Path) > 1 {
return []string{}, godata.NotImplementedError("multiple segments in $expand not supported")
}
expand = append(expand, item.Path[0].Value)
}
return expand, nil
}
// GetSearchValues extracts the value of the $search query parameter and returns
// it as a string. Rejects any search query that is more than just a simple string
func GetSearchValues(req *godata.GoDataQuery) (string, error) {
if req == nil || req.Search == nil {
return "", nil
}
// Only allow simple search queries for now
if len(req.Search.Tree.Children) != 0 {
return "", godata.NotImplementedError("complex search queries are not supported")
}
return req.Search.Tree.Token.Value, nil
}

View File

@@ -322,6 +322,7 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, newDrive)
}
// UpdateDrive updates the properties of a storage drive (space).
func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) {
logger := g.logger.SubloggerWithRequestID(r.Context())
logger.Info().Msg("calling update drive")
@@ -594,7 +595,7 @@ func (g Graph) cs3StorageSpaceToDrive(ctx context.Context, baseURL *url.URL, spa
} else {
var user libregraph.User
if item := g.usersCache.Get(id); item == nil {
if requestedUser, err := g.identityBackend.GetUser(ctx, id, url.Values{}); err == nil {
if requestedUser, err := g.identityBackend.GetUser(ctx, id, &godata.GoDataRequest{}); err == nil {
user = *requestedUser
g.usersCache.Set(id, user, ttlcache.DefaultTTL)
}
@@ -881,6 +882,7 @@ func listStorageSpacesTypeFilter(spaceType string) *storageprovider.ListStorageS
}
}
// DeleteDrive deletes a storage drive (space).
func (g Graph) DeleteDrive(w http.ResponseWriter, r *http.Request) {
logger := g.logger.SubloggerWithRequestID(r.Context())
logger.Info().Msg("calling delete drive")

View File

@@ -32,6 +32,14 @@ import (
func (g Graph) GetMe(w http.ResponseWriter, r *http.Request) {
logger := g.logger.SubloggerWithRequestID(r.Context())
logger.Info().Msg("calling get user in /me")
sanitizedPath := strings.TrimPrefix(r.URL.Path, "/graph/v1.0/")
odataReq, err := godata.ParseRequest(r.Context(), sanitizedPath, r.URL.Query())
if err != nil {
logger.Debug().Err(err).Interface("query", r.URL.Query()).Msg("could not get users: query error")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error())
return
}
u, ok := revactx.ContextGetUser(r.Context())
if !ok {
@@ -39,7 +47,14 @@ func (g Graph) GetMe(w http.ResponseWriter, r *http.Request) {
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "user not in context")
return
}
exp := strings.Split(r.URL.Query().Get("$expand"), ",")
exp, err := identity.GetExpandValues(odataReq.Query)
if err != nil {
logger.Debug().Err(err).Interface("query", r.URL.Query()).Msg("could not get users: $expand error")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error())
return
}
var me *libregraph.User
// We can just return the user from context unless we need to expand the group memberships
if !slices.Contains(exp, "memberOf") {
@@ -47,7 +62,7 @@ func (g Graph) GetMe(w http.ResponseWriter, r *http.Request) {
} else {
var err error
logger.Debug().Msg("calling get user on backend")
me, err = g.identityBackend.GetUser(r.Context(), u.GetId().GetOpaqueId(), r.URL.Query())
me, err = g.identityBackend.GetUser(r.Context(), u.GetId().GetOpaqueId(), odataReq)
if err != nil {
logger.Debug().Err(err).Interface("user", u).Msg("could not get user from backend")
var errcode errorcode.Error
@@ -111,7 +126,7 @@ func (g Graph) GetUsers(w http.ResponseWriter, r *http.Request) {
}
logger.Debug().Interface("query", r.URL.Query()).Msg("calling get users on backend")
users, err := g.identityBackend.GetUsers(r.Context(), r.URL.Query())
users, err := g.identityBackend.GetUsers(r.Context(), odataReq)
if err != nil {
logger.Debug().Err(err).Interface("query", r.URL.Query()).Msg("could not get users from backend")
var errcode errorcode.Error
@@ -123,8 +138,12 @@ func (g Graph) GetUsers(w http.ResponseWriter, r *http.Request) {
return
}
// expand appRoleAssignments if requested
exp := strings.Split(r.URL.Query().Get("$expand"), ",")
exp, err := identity.GetExpandValues(odataReq.Query)
if err != nil {
logger.Debug().Err(err).Interface("query", r.URL.Query()).Msg("could not get users: $expand error")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error())
return
}
expandAppRoleAssignments := slices.Contains(exp, "appRoleAssignments")
expandMemberOf := slices.Contains(exp, "memberOf")
for _, u := range users {
@@ -240,6 +259,9 @@ func (g Graph) PostUser(w http.ResponseWriter, r *http.Request) {
func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) {
logger := g.logger.SubloggerWithRequestID(r.Context())
logger.Info().Msg("calling get user")
sanitizedPath := strings.TrimPrefix(r.URL.Path, "/graph/v1.0/")
userID := chi.URLParam(r, "userID")
userID, err := url.PathUnescape(userID)
if err != nil {
@@ -254,8 +276,22 @@ func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) {
return
}
odataReq, err := godata.ParseRequest(r.Context(), sanitizedPath, r.URL.Query())
if err != nil {
logger.Debug().Err(err).Interface("query", r.URL.Query()).Msg("could not get users: query error")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error())
return
}
exp, err := identity.GetExpandValues(odataReq.Query)
if err != nil {
logger.Debug().Err(err).Interface("query", r.URL.Query()).Msg("could not get users: $expand error")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error())
return
}
logger.Debug().Str("id", userID).Msg("calling get user from backend")
user, err := g.identityBackend.GetUser(r.Context(), userID, r.URL.Query())
user, err := g.identityBackend.GetUser(r.Context(), userID, odataReq)
if err != nil {
logger.Debug().Err(err).Msg("could not get user: error fetching user from backend")
@@ -267,10 +303,9 @@ func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) {
}
return
}
sel := strings.Split(r.URL.Query().Get("$select"), ",")
exp := strings.Split(r.URL.Query().Get("$expand"), ",")
listDrives := slices.Contains(sel, "drives") || slices.Contains(exp, "drives")
listDrive := slices.Contains(sel, "drive") || slices.Contains(exp, "drive")
listDrives := slices.Contains(exp, "drives")
listDrive := slices.Contains(exp, "drive")
// do we need to list all or only the personal drive
filters := []*storageprovider.ListStorageSpacesRequest_Filter{}
@@ -368,6 +403,7 @@ func (g Graph) GetUser(w http.ResponseWriter, r *http.Request) {
func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) {
logger := g.logger.SubloggerWithRequestID(r.Context())
logger.Info().Msg("calling delete user")
sanitizedPath := strings.TrimPrefix(r.URL.Path, "/graph/v1.0/")
userID := chi.URLParam(r, "userID")
userID, err := url.PathUnescape(userID)
if err != nil {
@@ -381,8 +417,16 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) {
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "missing user id")
return
}
odataReq, err := godata.ParseRequest(r.Context(), sanitizedPath, r.URL.Query())
if err != nil {
logger.Debug().Err(err).Interface("query", r.URL.Query()).Msg("could not get users: query error")
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error())
return
}
logger.Debug().Str("id", userID).Msg("calling get user on user backend")
user, err := g.identityBackend.GetUser(r.Context(), userID, r.URL.Query())
user, err := g.identityBackend.GetUser(r.Context(), userID, odataReq)
if err != nil {
logger.Debug().Err(err).Str("userID", userID).Msg("failed to get user from backend")
var errcode errorcode.Error