Skip to content

Commit

Permalink
Add logic and unit test to json driver
Browse files Browse the repository at this point in the history
  • Loading branch information
ishank011 committed Jan 4, 2021
1 parent 1cef074 commit 293e546
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 32 deletions.
8 changes: 8 additions & 0 deletions changelog/unreleased/groupprovider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Enhancement: Add stubs and manager for groupprovider service

Recently, there was a separation of concerns with regard to users and groups in
CS3APIs. This PR adds the required stubs and drivers for the group manager.

https://github.com/cs3org/cs3apis/pull/99
https://github.com/cs3org/cs3apis/pull/102
https://github.com/cs3org/reva/pull/1358
1 change: 1 addition & 0 deletions cmd/revad/runtime/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
_ "github.com/cs3org/reva/pkg/auth/manager/loader"
_ "github.com/cs3org/reva/pkg/auth/registry/loader"
_ "github.com/cs3org/reva/pkg/cbox/loader"
_ "github.com/cs3org/reva/pkg/group/manager/loader"
_ "github.com/cs3org/reva/pkg/metrics/driver/loader"
_ "github.com/cs3org/reva/pkg/ocm/invite/manager/loader"
_ "github.com/cs3org/reva/pkg/ocm/provider/authorizer/loader"
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/cheggaaa/pb v1.0.29
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e
github.com/cs3org/go-cs3apis v0.0.0-20201130144553-72667e613e44
github.com/cs3org/go-cs3apis v0.0.0-20210104105209-0d3ecb3453dc
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59
github.com/go-ldap/ldap/v3 v3.2.4
Expand Down Expand Up @@ -53,6 +53,4 @@ go 1.13

replace github.com/eventials/go-tus => github.com/andrewmostello/go-tus v0.0.0-20200314041820-904a9904af9a

replace github.com/cs3org/go-cs3apis => github.com/ishank011/go-cs3apis v0.0.0-20201203124746-b2676dc530d8

replace google.golang.org/grpc => google.golang.org/grpc v1.26.0 // temporary downgrade
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ github.com/cs3org/go-cs3apis v0.0.0-20201118090759-87929f5bae21 h1:mZpylrgnCgSea
github.com/cs3org/go-cs3apis v0.0.0-20201118090759-87929f5bae21/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/go-cs3apis v0.0.0-20201130144553-72667e613e44 h1:bvVU3EesXzpOJu+Sh6bffwCOaF7mW3KxRVaEmDpIw38=
github.com/cs3org/go-cs3apis v0.0.0-20201130144553-72667e613e44/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/go-cs3apis v0.0.0-20210104105209-0d3ecb3453dc h1:vHFqu+Gb/iOKYFy2KswpwIG3G6zRMudRn+rQ2bg3TPE=
github.com/cs3org/go-cs3apis v0.0.0-20210104105209-0d3ecb3453dc/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down
24 changes: 0 additions & 24 deletions pkg/cbox/user/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,30 +431,6 @@ func (m *manager) FindUsers(ctx context.Context, query string) ([]*userpb.User,
return userSlice, nil
}

func (m *manager) FindGroups(ctx context.Context, query string) ([]string, error) {
url := fmt.Sprintf("%s/Group?filter=groupIdentifier:contains:%s", m.conf.APIBaseURL, query)
responseData, err := m.sendAPIRequest(ctx, url)
if err != nil {
return nil, err
}

groupSet := make(map[string]bool)
for _, g := range responseData {
group, ok := g.(map[string]interface{})
if !ok {
return nil, errors.New("rest: error in type assertion")
}
groupSet[group["groupIdentifier"].(string)] = true
}

groups := []string{}
for k := range groupSet {
groups = append(groups, k)
}

return groups, nil
}

func (m *manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error) {

groups, err := m.fetchCachedUserGroups(uid)
Expand Down
61 changes: 56 additions & 5 deletions pkg/group/manager/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"context"
"encoding/json"
"io/ioutil"
"strconv"
"strings"

grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
Expand Down Expand Up @@ -86,21 +88,70 @@ func New(m map[string]interface{}) (group.Manager, error) {
}

func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId) (*grouppb.Group, error) {
return nil, errtypes.NotSupported("json: GetGroup is not implemented")
for _, g := range m.groups {
if g.Id.GetOpaqueId() == gid.OpaqueId || g.GroupName == gid.OpaqueId {
return g, nil
}
}
return nil, errtypes.NotFound(gid.OpaqueId)
}

func (m *manager) GetGroupByClaim(ctx context.Context, claim, value string) (*grouppb.Group, error) {
return nil, errtypes.NotSupported("json: GetGroupByClaim is not implemented")
for _, g := range m.groups {
if groupClaim, err := extractClaim(g, claim); err == nil && value == groupClaim {
return g, nil
}
}
return nil, errtypes.NotFound(value)
}

func extractClaim(g *grouppb.Group, claim string) (string, error) {
switch claim {
case "group_name":
return g.GroupName, nil
case "gid_number":
return strconv.FormatInt(g.GidNumber, 10), nil
case "display_name":
return g.DisplayName, nil
case "mail":
return g.Mail, nil
}
return "", errors.New("json: invalid field")
}

func (m *manager) FindGroups(ctx context.Context, query string) ([]*grouppb.Group, error) {
return nil, errtypes.NotSupported("json: FindGroups is not implemented")
groups := []*grouppb.Group{}
for _, g := range m.groups {
if groupContains(g, query) {
groups = append(groups, g)
}
}
return groups, nil
}

func groupContains(g *grouppb.Group, query string) bool {
return strings.Contains(g.GroupName, query) || strings.Contains(g.DisplayName, query) || strings.Contains(g.Mail, query) || strings.Contains(g.Id.OpaqueId, query)
}

func (m *manager) GetMembers(ctx context.Context, gid *grouppb.GroupId) ([]*userpb.UserId, error) {
return nil, errtypes.NotSupported("json: GetMembers is not implemented")
for _, g := range m.groups {
if g.Id.GetOpaqueId() == gid.OpaqueId || g.GroupName == gid.OpaqueId {
return g.Members, nil
}
}
return nil, errtypes.NotFound(gid.OpaqueId)
}

func (m *manager) HasMember(ctx context.Context, gid *grouppb.GroupId, uid *userpb.UserId) (bool, error) {
return false, errtypes.NotSupported("json: HasMember is not implemented")
members, err := m.GetMembers(ctx, gid)
if err != nil {
return false, err
}

for _, u := range members {
if u.OpaqueId == uid.OpaqueId && u.Idp == uid.Idp {
return true, nil
}
}
return false, nil
}
159 changes: 159 additions & 0 deletions pkg/group/manager/json/json_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// Copyright 2018-2020 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

package json

import (
"context"
"io/ioutil"
"os"
"reflect"
"testing"

grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
"github.com/cs3org/reva/pkg/errtypes"
)

var ctx = context.Background()

func TestUserManager(t *testing.T) {
// add tempdir
tempdir, err := ioutil.TempDir("", "json_test")
if err != nil {
t.Fatalf("error while create temp dir: %v", err)
}
defer os.RemoveAll(tempdir)

// corrupt json object with user meta data
userJSON := `[{`

// get file handler for temporary file
file, err := ioutil.TempFile(tempdir, "json_test")
if err != nil {
t.Fatalf("error while open temp file: %v", err)
}

// write json object to tempdir
_, err = file.WriteString(userJSON)
if err != nil {
t.Fatalf("error while writing temp file: %v", err)
}

// get manager
input := map[string]interface{}{
"groups": file.Name(),
}
_, err = New(input)
if err == nil {
t.Fatalf("no error (but we expected one) while get manager")
}

// clean up
os.Remove(file.Name())

// json object with user meta data
userJSON = `[{"id":{"opaque_id":"sailing-lovers"},"group_name":"sailing-lovers","mail":"sailing-lovers@example.org","display_name":"Sailing Lovers","gid_number":1234,"members":[{"idp":"localhost","opaque_id":"einstein"},{"idp":"localhost","opaque_id":"marie"}]}]`

// get file handler for temporary file
file, err = ioutil.TempFile(tempdir, "json_test")
if err != nil {
t.Fatalf("error while open temp file: %v", err)
}
defer os.Remove(file.Name())

// write json object to tempdir
_, err = file.WriteString(userJSON)
if err != nil {
t.Fatalf("error while writing temp file: %v", err)
}

// get manager - positive test
input = map[string]interface{}{
"groups": file.Name(),
}
manager, _ := New(input)

// setup test data
gid := &grouppb.GroupId{OpaqueId: "sailing-lovers"}
uidEinstein := &userpb.UserId{Idp: "localhost", OpaqueId: "einstein"}
uidMarie := &userpb.UserId{Idp: "localhost", OpaqueId: "marie"}
members := []*userpb.UserId{uidEinstein, uidMarie}
group := &grouppb.Group{
Id: gid,
GroupName: "sailing-lovers",
Mail: "sailing-lovers@example.org",
GidNumber: 1234,
DisplayName: "Sailing Lovers",
Members: members,
}
groupFake := &grouppb.GroupId{OpaqueId: "fake-group"}

// positive test GetGroup
resGroup, _ := manager.GetGroup(ctx, gid)
if !reflect.DeepEqual(resGroup, group) {
t.Fatalf("group differs: expected=%v got=%v", group, resGroup)
}

// negative test GetGroup
expectedErr := errtypes.NotFound(groupFake.OpaqueId)
_, err = manager.GetGroup(ctx, groupFake)
if !reflect.DeepEqual(err, expectedErr) {
t.Fatalf("group not found error differ: expected='%v' got='%v'", expectedErr, err)
}

// positive test GetGroupByClaim by mail
resGroupByEmail, _ := manager.GetGroupByClaim(ctx, "mail", "sailing-lovers@example.org")
if !reflect.DeepEqual(resGroupByEmail, group) {
t.Fatalf("group differs: expected=%v got=%v", group, resGroupByEmail)
}

// negative test GetGroupByClaim by mail
expectedErr = errtypes.NotFound("abc@example.com")
_, err = manager.GetGroupByClaim(ctx, "mail", "abc@example.com")
if !reflect.DeepEqual(err, expectedErr) {
t.Fatalf("group not found error differs: expected='%v' got='%v'", expectedErr, err)
}

// test GetMembers
resMembers, _ := manager.GetMembers(ctx, gid)
if !reflect.DeepEqual(resMembers, members) {
t.Fatalf("members differ: expected=%v got=%v", members, resMembers)
}

// positive test HasMember
resMember, _ := manager.HasMember(ctx, gid, uidMarie)
if resMember != true {
t.Fatalf("result differs: expected=%v got=%v", true, resMember)
}

// negative test HasMember
resMemberNegative, _ := manager.HasMember(ctx, gid, &userpb.UserId{Idp: "localhost", OpaqueId: "fake-user"})
if resMemberNegative != false {
t.Fatalf("result differs: expected=%v got=%v", false, resMemberNegative)
}

// test FindGroups
resFind, _ := manager.FindGroups(ctx, "sail")
if len(resFind) != 1 {
t.Fatalf("too many groups found: expected=%d got=%d", 1, len(resFind))
}
if !reflect.DeepEqual(resFind[0].GroupName, "sailing-lovers") {
t.Fatalf("group differ: expected=%v got=%v", "sailing-lovers", resFind[0].GroupName)
}
}

0 comments on commit 293e546

Please sign in to comment.