From 3847f9f9e20f37716ac809feb18213671bab9ad6 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Tue, 10 May 2022 12:44:52 +0200 Subject: [PATCH] Remove accounts service remainders from ocs - proxy routes everything user/group related (except of `user/signing-key`) to the reva ocs endpoint now - remove the unused user and group methods from ocs --- extensions/ocs/pkg/server/http/svc_test.go | 2238 ----------------- extensions/ocs/pkg/service/v0/service.go | 44 - .../pkg/config/defaults/defaultconfig.go | 2 +- 3 files changed, 1 insertion(+), 2283 deletions(-) delete mode 100644 extensions/ocs/pkg/server/http/svc_test.go diff --git a/extensions/ocs/pkg/server/http/svc_test.go b/extensions/ocs/pkg/server/http/svc_test.go deleted file mode 100644 index e4e2546d4cc..00000000000 --- a/extensions/ocs/pkg/server/http/svc_test.go +++ /dev/null @@ -1,2238 +0,0 @@ -package http - -import ( - "context" - "encoding/json" - "encoding/xml" - "fmt" - "io/ioutil" - "log" - "net/http" - "net/http/httptest" - "net/url" - "path/filepath" - "strings" - "testing" - - user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" - types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" - "github.com/cs3org/reva/v2/pkg/auth/scope" - "github.com/cs3org/reva/v2/pkg/token" - "github.com/cs3org/reva/v2/pkg/token/manager/jwt" - "github.com/golang/protobuf/ptypes/empty" - accountsCfg "github.com/owncloud/ocis/v2/extensions/accounts/pkg/config" - accountsLogging "github.com/owncloud/ocis/v2/extensions/accounts/pkg/logging" - accountsServiceExt "github.com/owncloud/ocis/v2/extensions/accounts/pkg/service/v0" - "github.com/owncloud/ocis/v2/extensions/ocs/pkg/config" - svc "github.com/owncloud/ocis/v2/extensions/ocs/pkg/service/v0" - ssvc "github.com/owncloud/ocis/v2/extensions/settings/pkg/service/v0" - ocisLog "github.com/owncloud/ocis/v2/ocis-pkg/log" - "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc" - accountsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/accounts/v0" - settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0" - accountssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/accounts/v0" - settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0" - "github.com/stretchr/testify/assert" - "go-micro.dev/v4/client" -) - -const ( - ocsV1 string = "v1.php" - ocsV2 string = "v2.php" -) - -const unsuccessfulResponseText string = "The response was expected to be successful but was not" - -const ( - userProvisioningEndPoint string = "/v1.php/cloud/users?format=json" - groupProvisioningEndPoint string = "/v1.php/cloud/groups?format=json" -) - -const ( - userEinstein string = "einstein" - userMarie string = "marie" - userRichard string = "richard" - userIDP string = "idp" - userReva string = "reva" - userMoss string = "moss" - userAdmin string = "admin" - userKatherine string = "katherine" -) -const ( - groupPhilosophyHaters string = "philosophy-haters" - groupPhysicsLovers string = "physics-lovers" - groupPoloniumLovers string = "polonium-lovers" - groupQuantumLovers string = "quantum-lovers" - groupRadiumLovers string = "radium-lovers" - groupSailingLovers string = "sailing-lovers" - groupViolinHaters string = "violin-haters" - groupUsers string = "users" - groupSysUsers string = "sysusers" -) - -var defaultMemberOf = map[string][]string{ - userEinstein: { - groupUsers, - groupSailingLovers, - groupViolinHaters, - groupPhysicsLovers, - }, - userIDP: { - groupSysUsers, - }, - userRichard: { - groupUsers, - groupQuantumLovers, - groupPhilosophyHaters, - groupPhysicsLovers, - }, - userReva: { - groupSysUsers, - }, - userMarie: { - groupUsers, - groupRadiumLovers, - groupPoloniumLovers, - groupPhysicsLovers, - }, - userMoss: { - groupUsers, - }, - userAdmin: { - groupUsers, - }, - userKatherine: { - groupUsers, - groupSailingLovers, - groupQuantumLovers, - groupPhysicsLovers, - }, -} - -var defaultMembers = map[string][]string{ - groupSysUsers: { - userIDP, - userReva, - }, - groupUsers: { - userEinstein, - userMarie, - userRichard, - userKatherine, - }, - groupSailingLovers: { - userEinstein, - userKatherine, - }, - groupViolinHaters: { - userEinstein, - }, - groupPoloniumLovers: { - userMarie, - }, - groupQuantumLovers: { - userRichard, - userKatherine, - }, - groupPhilosophyHaters: { - userRichard, - }, - groupPhysicsLovers: { - userEinstein, - userMarie, - userRichard, - userKatherine, - }, -} - -// These account ids are only needed for cleanup -const ( - userIDEinstein string = "4c510ada-c86b-4815-8820-42cdf82c3d51" - userIDMarie string = "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c" - userIDFeynman string = "932b4540-8d16-481e-8ef4-588e4b6b151c" - userIDIDP string = "820ba2a1-3f54-4538-80a4-2d73007e30bf" - userIDReva string = "bc596f3c-c955-4328-80a0-60d018b4ad57" - userIDMoss string = "058bff95-6708-4fe5-91e4-9ea3d377588b" - userIDAdmin string = "ddc2004c-0977-11eb-9d3f-a793888cd0f8" - userIDKatherine string = "534bb038-6f9d-4093-946f-133be61fa4e7" -) - -// These group ids are only needed for cleanup -const ( - groupIDPhilosophyHaters = "167cbee2-0518-455a-bfb2-031fe0621e5d" - groupIDPhysicsLovers = "262982c1-2362-4afa-bfdf-8cbfef64a06e" - groupIDPoloniumLovers = "cedc21aa-4072-4614-8676-fa9165f598ff" - groupIDQuantumLovers = "a1726108-01f8-4c30-88df-2b1a9d1cba1a" - groupIDRadiumLovers = "7b87fd49-286e-4a5f-bafd-c535d5dd997a" - groupIDSailingLovers = "6040aa17-9c64-4fef-9bd0-77234d71bad0" - groupIDViolinHaters = "dd58e5ec-842e-498b-8800-61f2ec6f911f" - groupIDUsers = "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa" - groupIDSysUsers = "34f38767-c937-4eb6-b847-1c175829a2a0" -) - -const jwtSecret = "HELLO-secret" - -var service = grpc.Service{} -var tokenManager token.Manager - -var mockedRoleAssignment = map[string]string{} - -var ocsVersions = []string{ocsV1, ocsV2} - -var formats = []string{"json", "xml"} - -var dataPath = createTmpDir() - -var defaultPassword = "Testing123" - -var defaultUsers = []string{ - userEinstein, - userIDP, - userRichard, - userReva, - userMarie, - userMoss, - userAdmin, - userKatherine, -} -var defaultUserIDs = []string{ - userIDEinstein, - userIDIDP, - userIDFeynman, - userIDReva, - userIDMarie, - userIDMoss, - userIDAdmin, - userIDKatherine, -} - -var defaultGroups = []string{ - groupPhilosophyHaters, - groupPhysicsLovers, - groupSysUsers, - groupUsers, - groupSailingLovers, - groupRadiumLovers, - groupQuantumLovers, - groupPoloniumLovers, - groupViolinHaters, -} -var defaultGroupIDs = []string{ - groupIDPhilosophyHaters, - groupIDPhysicsLovers, - groupIDSysUsers, - groupIDUsers, - groupIDSailingLovers, - groupIDRadiumLovers, - groupIDQuantumLovers, - groupIDPoloniumLovers, - groupIDViolinHaters, -} - -func getFormatString(format string) string { - if format == "json" { - return "?format=json" - } else if format == "xml" { - return "" - } else { - panic("Invalid format received") - } -} - -func createTmpDir() string { - name, err := ioutil.TempDir("/tmp", "ocis-accounts-store-") - if err != nil { - panic(err) - } - - return name -} - -type Quota struct { - Free int64 `json:"free" xml:"free"` - Used int64 `json:"used" xml:"used"` - Total int64 `json:"total" xml:"total"` - Relative float32 `json:"relative" xml:"relative"` - Definition string `json:"definition" xml:"definition"` -} - -type User struct { - Enabled string `json:"enabled" xml:"enabled"` - ID string `json:"id" xml:"id"` - Email string `json:"email" xml:"email"` - Password string `json:"-" xml:"-"` - Quota Quota `json:"quota" xml:"quota"` - UIDNumber int `json:"uidnumber" xml:"uidnumber"` - GIDNumber int `json:"gidnumber" xml:"gidnumber"` - Displayname string `json:"displayname" xml:"displayname"` -} - -func (u *User) getUserRequestString() string { - res := url.Values{} - - if u.Password != "" { - res.Add("password", u.Password) - } - - if u.ID != "" { - res.Add("userid", u.ID) - } - - if u.Email != "" { - res.Add("email", u.Email) - } - - if u.Displayname != "" { - res.Add("displayname", u.Displayname) - } - - if u.UIDNumber != 0 { - res.Add("uidnumber", fmt.Sprint(u.UIDNumber)) - } - - if u.GIDNumber != 0 { - res.Add("gidnumber", fmt.Sprint(u.GIDNumber)) - } - - return res.Encode() -} - -type Group struct { - ID string `json:"id" xml:"id"` - GIDNumber int `json:"gidnumber" xml:"gidnumber"` - Displayname string `json:"displayname" xml:"displayname"` -} - -func (g *Group) getGroupRequestString() string { - res := url.Values{} - - if g.ID != "" { - res.Add("groupid", g.ID) - } - - if g.Displayname != "" { - res.Add("displayname", g.Displayname) - } - if g.GIDNumber != 0 { - res.Add("gidnumber", fmt.Sprint(g.GIDNumber)) - } - - return res.Encode() -} - -type Meta struct { - Status string `json:"status" xml:"status"` - StatusCode int `json:"statuscode" xml:"statuscode"` - Message string `json:"message" xml:"message"` -} - -func (m *Meta) Success(ocsVersion string) bool { - if !(ocsVersion == ocsV1 || ocsVersion == ocsV2) { - return false - } - if m.Status != "ok" { - return false - } - if ocsVersion == ocsV1 && m.StatusCode != 100 { - return false - } else if ocsVersion == ocsV2 && m.StatusCode != 200 { - return false - } else { - return true - } -} - -type SingleUserResponse struct { - Ocs struct { - Meta Meta `json:"meta" xml:"meta"` - Data User `json:"data" xml:"data"` - } `json:"ocs" xml:"ocs"` -} - -type GetUsersResponse struct { - Ocs struct { - Meta Meta `json:"meta" xml:"meta"` - Data struct { - Users []string `json:"users" xml:"users>element"` - } `json:"data" xml:"data"` - } `json:"ocs" xml:"ocs"` -} - -type EmptyResponse struct { - Ocs struct { - Meta Meta `json:"meta" xml:"meta"` - Data struct { - } `json:"data" xml:"data"` - } `json:"ocs" xml:"ocs"` -} - -func assertEmptyResponse(t *testing.T, format string, res *httptest.ResponseRecorder) *EmptyResponse { - var response EmptyResponse - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Log(res.Body.String()) - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Log(res.Body.String()) - t.Fatal(err) - } - } - return &response -} - -type GetUsersGroupsResponse struct { - Ocs struct { - Meta Meta `json:"meta" xml:"meta"` - Data struct { - Groups []string `json:"groups" xml:"groups>element"` - } `json:"data" xml:"data"` - } `json:"ocs" xml:"ocs"` -} - -type OcsConfig struct { - Version string `json:"version" xml:"version"` - Website string `json:"website" xml:"website"` - Host string `json:"host" xml:"host"` - Contact string `json:"contact" xml:"contact"` - Ssl string `json:"ssl" xml:"ssl"` -} - -type GetConfigResponse struct { - Ocs struct { - Meta Meta `json:"meta" xml:"meta"` - Data OcsConfig `json:"data" xml:"data"` - } `json:"ocs" xml:"ocs"` -} - -func assertStatusCode(t *testing.T, statusCode int, res *httptest.ResponseRecorder, ocsVersion string) { - if ocsVersion == ocsV1 { - assert.Equal(t, 200, res.Code) - } else { - assert.Equal(t, statusCode, res.Code) - } -} - -type GetGroupsResponse struct { - Ocs struct { - Meta Meta `json:"meta" xml:"meta"` - Data struct { - Groups []string `json:"groups" xml:"groups>element"` - } `json:"data" xml:"data"` - } `json:"ocs" xml:"ocs"` -} - -type GetGroupMembersResponse struct { - Ocs struct { - Meta Meta `json:"meta" xml:"meta"` - Data struct { - Users []string `json:"users" xml:"users>element"` - } `json:"data" xml:"data"` - } `json:"ocs" xml:"ocs"` -} - -func assertResponseMeta(t *testing.T, expected, actual Meta) { - assert.Equal(t, expected.Status, actual.Status, "The status of response doesn't match") - assert.Equal(t, expected.StatusCode, actual.StatusCode, "The Status code of response doesn't match") - assert.Equal(t, expected.Message, actual.Message, "The Message of response doesn't match") -} - -// compares users at tha /user endpoint -func assertUserSame(t *testing.T, expected, actual User) { - if expected.ID == "" { - // Check the auto generated userId - assert.Regexp( - t, - "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}", - actual.ID, "the userid is not a valid uuid", - ) - } else { - assert.Equal(t, expected.ID, actual.ID, "UserId doesn't match for user %v", expected.ID) - } - assert.Equal(t, expected.Email, actual.Email, "email doesn't match for user %v", expected.ID) - // /user has no enabled flag - if expected.Displayname == "" { - assert.Equal(t, expected.ID, actual.Displayname, "displayname doesn't match for user %v", expected.ID) - } else { - assert.Equal(t, expected.Displayname, actual.Displayname, "displayname doesn't match for user %v", expected.ID) - } - // /user has no quota, uid or gid -} - -// compares users at the /users/ endpoint -func assertUsersSame(t *testing.T, expected, actual User, quotaAvailable bool) { - if expected.ID == "" { - // Check the auto generated userId - assert.Regexp( - t, - "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}", - actual.ID, "the userid is not a valid uuid", - ) - } else { - assert.Equal(t, expected.ID, actual.ID, "UserId doesn't match for user %v", expected.ID) - } - assert.Equal(t, expected.Email, actual.Email, "email doesn't match for user %v", expected.ID) - assert.Equal(t, expected.Enabled, actual.Enabled, "enabled doesn't match for user %v", expected.ID) - if expected.Displayname == "" { - assert.Equal(t, expected.ID, actual.Displayname, "displayname doesn't match for user %v", expected.ID) - } else { - assert.Equal(t, expected.Displayname, actual.Displayname, "displayname doesn't match for user %v", expected.ID) - } - if quotaAvailable { - assert.NotZero(t, actual.Quota.Free) - assert.NotZero(t, actual.Quota.Used) - assert.NotZero(t, actual.Quota.Total) - assert.Equal(t, "default", actual.Quota.Definition) - } else { - assert.Equal(t, expected.Quota, actual.Quota, "Quota match for user %v", expected.ID) - } - - if expected.UIDNumber != 0 { - assert.Equal(t, expected.UIDNumber, actual.UIDNumber, "UidNumber doesn't match for user %s", expected.ID) - } - if expected.GIDNumber != 0 { - assert.Equal(t, expected.GIDNumber, actual.GIDNumber, "GidNumber doesn't match for user %s", expected.ID) - } -} - -func findAccount(t *testing.T, username string) (*accountsmsg.Account, error) { - cl := accountssvc.NewAccountsService("com.owncloud.api.accounts", service.Client()) - - req := &accountssvc.ListAccountsRequest{ - Query: "preferred_name eq '" + username + "'", - } - res, err := cl.ListAccounts(context.Background(), req) - if err != nil { - return nil, err - } - if len(res.Accounts) == 0 { - return nil, fmt.Errorf("username %s not found", username) - } - return res.Accounts[0], err -} - -func deleteAccount(t *testing.T, id string) (*empty.Empty, error) { - cl := accountssvc.NewAccountsService("com.owncloud.api.accounts", service.Client()) - - req := &accountssvc.DeleteAccountRequest{Id: id} - res, err := cl.DeleteAccount(context.Background(), req) - return res, err -} - -func deleteGroup(t *testing.T, id string) (*empty.Empty, error) { - cl := accountssvc.NewGroupsService("com.owncloud.api.accounts", service.Client()) - - req := &accountssvc.DeleteGroupRequest{Id: id} - res, err := cl.DeleteGroup(context.Background(), req) - return res, err -} - -func buildRoleServiceMock() settingssvc.RoleService { - return settingssvc.MockRoleService{ - AssignRoleToUserFunc: func(ctx context.Context, req *settingssvc.AssignRoleToUserRequest, opts ...client.CallOption) (res *settingssvc.AssignRoleToUserResponse, err error) { - mockedRoleAssignment[req.AccountUuid] = req.RoleId - return &settingssvc.AssignRoleToUserResponse{ - Assignment: &settingsmsg.UserRoleAssignment{ - AccountUuid: req.AccountUuid, - RoleId: req.RoleId, - }, - }, nil - }, - ListRolesFunc: func(ctx context.Context, req *settingssvc.ListBundlesRequest, opts ...client.CallOption) (*settingssvc.ListBundlesResponse, error) { - return &settingssvc.ListBundlesResponse{ - Bundles: []*settingsmsg.Bundle{ - { - Id: ssvc.BundleUUIDRoleAdmin, - Settings: []*settingsmsg.Setting{ - { - Id: accountsServiceExt.AccountManagementPermissionID, - }, - }, - }, - { - Id: ssvc.BundleUUIDRoleUser, - Settings: []*settingsmsg.Setting{ - { - Id: accountsServiceExt.SelfManagementPermissionID, - }, - }, - }, - }, - }, nil - }, - } -} - -func init() { - service = grpc.NewService( - grpc.Namespace("com.owncloud.api"), - grpc.Name("accounts"), - grpc.Address("localhost:9180"), - ) - - c := &accountsCfg.Config{ - DemoUsersAndGroups: true, - Repo: accountsCfg.Repo{ - Backend: "disk", - Disk: accountsCfg.Disk{ - Path: dataPath, - }, - }, - Log: &accountsCfg.Log{ - Level: "info", - Pretty: true, - Color: true, - }, - } - - var hdlr *accountsServiceExt.Service - var err error - - if hdlr, err = accountsServiceExt.New( - accountsServiceExt.Logger(accountsLogging.Configure("accounts", c.Log)), - accountsServiceExt.Config(c), - accountsServiceExt.RoleService(buildRoleServiceMock()), - ); err != nil { - log.Fatalf("Could not create new service") - } - - err = accountssvc.RegisterAccountsServiceHandler(service.Server(), hdlr) - if err != nil { - log.Fatal("could not register the Accounts handler") - } - err = accountssvc.RegisterGroupsServiceHandler(service.Server(), hdlr) - if err != nil { - log.Fatal("could not register the Groups handler") - } - - err = service.Server().Start() - if err != nil { - log.Fatalf("could not start server: %v", err) - } - - // a token manager to mint tokens - tokenManager, err = jwt.New(map[string]interface{}{ - "secret": jwtSecret, - }) - if err != nil { - log.Fatalf("could not create token manager: %v", err) - } -} - -func cleanUp(t *testing.T) { - datastore := filepath.Join(dataPath, "accounts") - - files, err := ioutil.ReadDir(datastore) - if err != nil { - log.Fatal(err) - } - - for _, f := range files { - found := false - for _, defUser := range defaultUserIDs { - if f.Name() == defUser { - found = true - break - } - } - - if !found { - if _, err := deleteAccount(t, f.Name()); err != nil { - panic(err) - } - } - } - - datastoreGroups := filepath.Join(dataPath, "groups") - - files, err = ioutil.ReadDir(datastoreGroups) - if err != nil { - log.Fatal(err) - } - - for _, f := range files { - found := false - for _, defGrp := range defaultGroupIDs { - if f.Name() == defGrp { - found = true - break - } - } - - if !found { - if _, err := deleteGroup(t, f.Name()); err != nil { - panic(err) - } - } - } -} - -func mintToken(ctx context.Context, su *User, roleIds []string) (token string, err error) { - roleIDsJSON, err := json.Marshal(roleIds) - if err != nil { - return "", err - } - u := &user.User{ - Id: &user.UserId{ - OpaqueId: su.ID, - }, - Opaque: &types.Opaque{ - Map: map[string]*types.OpaqueEntry{ - "roles": { - Decoder: "json", - Value: roleIDsJSON, - }, - }, - }, - Groups: []string{}, - UidNumber: int64(su.UIDNumber), - GidNumber: int64(su.GIDNumber), - } - s, _ := scope.AddOwnerScope(nil) - return tokenManager.MintToken(ctx, u, s) -} - -func sendRequest(method, endpoint, body string, u *User, roleIds []string) (*httptest.ResponseRecorder, error) { - var reader = strings.NewReader(body) - req, err := http.NewRequest(method, endpoint, reader) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - - if u != nil { - token, err := mintToken(context.Background(), u, roleIds) - if err != nil { - return nil, err - } - req.Header.Set("x-access-token", token) - } - - rr := httptest.NewRecorder() - - service := getService() - service.ServeHTTP(rr, req) - - return rr, nil -} - -func getService() svc.Service { - c := &config.Config{ - HTTP: config.HTTP{ - Root: "/", - Addr: "localhost:9110", - }, - Reva: &config.Reva{}, - TokenManager: &config.TokenManager{ - JWTSecret: jwtSecret, - }, - Log: &config.Log{ - Level: "debug", - }, - } - - var logger ocisLog.Logger - - return svc.NewService( - svc.Logger(logger), - svc.Config(c), - svc.RoleService(buildRoleServiceMock()), - ) -} - -func createUser(u User) error { - // add default password if not set differently - if u.Password == "" { - u.Password = defaultPassword - } - _, err := sendRequest( - "POST", - userProvisioningEndPoint, - u.getUserRequestString(), - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - return err - } - return nil -} - -func createGroup(g Group) error { //lint:file-ignore U1000 not implemented - _, err := sendRequest( - "POST", - groupProvisioningEndPoint, - g.getGroupRequestString(), - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - return err - } - return nil -} - -func TestCreateUser(t *testing.T) { - scenarios := []struct { - name string - user User - err *Meta - }{ - { - "A simple user", - User{ - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "ErnestRutherFord", - Password: "newPassword", - }, - nil, - }, - { - "User with Uid and Gid defined", - User{ - Enabled: "true", - ID: "thomson", - Email: "thomson@example.com", - Displayname: "J. J. Thomson", - UIDNumber: 20027, - GIDNumber: 30000, - Password: "newPassword", - }, - nil, - }, - // https://github.com/owncloud/ocis/v2-ocs/issues/49 - { - "User with special character in userid", - User{ - Enabled: "true", - ID: "schrödinger", - Email: "schrödinger@example.com", - Displayname: "Erwin Schrödinger", - Password: "newPassword", - }, - &Meta{ - Status: "error", - StatusCode: 400, - Message: "preferred_name 'schrödinger' must be at least the local part of an email", - }, - }, - { - "User with different userid and email", - User{ - Enabled: "true", - ID: "planck", - Email: "max@example.com", - Displayname: "Max Planck", - Password: "newPassword", - }, - nil, - }, - { - "User without displayname", - User{ - Enabled: "true", - ID: "oppenheimer", - Email: "robert@example.com", - Password: "newPassword", - }, - nil, - }, - { - "User wit invalid email", - User{ - Enabled: "true", - ID: "chadwick", - Email: "not_a_email", - Password: "newPassword", - }, - &Meta{ - Status: "error", - StatusCode: 400, - Message: "mail 'not_a_email' must be a valid email", - }, - }, - { - "User without email", - User{ - Enabled: "true", - ID: "chadwick", - Password: "newPassword", - }, - &Meta{ - Status: "error", - StatusCode: 400, - Message: "mail '' must be a valid email", - }, - }, - { - "User without userid", - User{ - Enabled: "true", - Email: "james@example.com", - Password: "newPassword", - }, - &Meta{ - Status: "error", - StatusCode: 400, - Message: "preferred_name '' must be at least the local part of an email", - }, - }, - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - for _, scenario := range scenarios { - t.Run(fmt.Sprintf("%s (ocs=%s, format=%s)", scenario.name, ocsVersion, format), func(t *testing.T) { - formatpart := getFormatString(format) - res, err := sendRequest( - "POST", - fmt.Sprintf("/%v/cloud/users%v", ocsVersion, formatpart), - scenario.user.getUserRequestString(), - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - assert.NoError(t, err) - - var response SingleUserResponse - if format == "json" { - err = json.Unmarshal(res.Body.Bytes(), &response) - assert.NoError(t, err) - } else { - err = xml.Unmarshal(res.Body.Bytes(), &response.Ocs) - assert.NoError(t, err) - } - - if scenario.err == nil { - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - assertStatusCode(t, 200, res, ocsVersion) - assertUsersSame(t, scenario.user, response.Ocs.Data, false) - } else { - assertStatusCode(t, 400, res, ocsVersion) - assertResponseMeta(t, *scenario.err, response.Ocs.Meta) - } - - var id string - if scenario.user.ID != "" { - id = scenario.user.ID - } else { - id = response.Ocs.Data.ID - } - - res, err = sendRequest( - "GET", - userProvisioningEndPoint, - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - assert.NoError(t, err) - - var usersResponse GetUsersResponse - err = json.Unmarshal(res.Body.Bytes(), &usersResponse) - assert.NoError(t, err) - - assert.True(t, usersResponse.Ocs.Meta.Success(ocsV1), unsuccessfulResponseText) - - if scenario.err == nil { - assert.Contains(t, usersResponse.Ocs.Data.Users, id) - } else { - assert.NotContains(t, usersResponse.Ocs.Data.Users, scenario.user.ID) - } - cleanUp(t) - }) - } - } - } -} - -func TestGetUsers(t *testing.T) { - users := []User{ - { - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - }, - { - Enabled: "true", - ID: "thomson", - Email: "thomson@example.com", - Displayname: "J. J. Thomson", - }, - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - for _, user := range users { - err := createUser(user) - if err != nil { - t.Fatal(err) - } - } - - formatpart := getFormatString(format) - res, err := sendRequest( - "GET", - fmt.Sprintf("/%v/cloud/users%v", ocsVersion, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var response GetUsersResponse - - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - for _, user := range users { - assert.Contains(t, response.Ocs.Data.Users, user.ID) - } - cleanUp(t) - } - } -} - -func TestGetUsersDefaultUsers(t *testing.T) { - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - res, err := sendRequest( - "GET", - fmt.Sprintf("/%v/cloud/users%v", ocsVersion, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var response GetUsersResponse - - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - for _, user := range defaultUsers { - assert.Contains(t, response.Ocs.Data.Users, user) - } - cleanUp(t) - } - } -} - -func TestGetUser(t *testing.T) { - users := []User{ - { - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - }, - { - Enabled: "true", - ID: "thomson", - Email: "thomson@example.com", - Displayname: "J. J. Thomson", - }, - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - - for _, user := range users { - err := createUser(user) - if err != nil { - t.Fatal(err) - } - } - formatpart := getFormatString(format) - for _, user := range users { - res, err := sendRequest( - "GET", - fmt.Sprintf("/%s/cloud/users/%s%s", ocsVersion, user.ID, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var response SingleUserResponse - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to pass but it failed") - assertUsersSame(t, user, response.Ocs.Data, true) - } - cleanUp(t) - } - } -} - -func TestGetUserInvalidId(t *testing.T) { - invalidUsers := []string{ - "1", - "invalid", - "3434234233", - "1am41validUs3r", - "_-@@--$$__", - } - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, user := range invalidUsers { - res, err := sendRequest( - "GET", - fmt.Sprintf("/%s/cloud/user/%s%s", ocsVersion, user, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var response SingleUserResponse - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 404, res, ocsVersion) - assert.False(t, response.Ocs.Meta.Success(ocsVersion), "the response was expected to fail but passed") - assertResponseMeta(t, Meta{ - Status: "error", - StatusCode: 998, - Message: "not found", - }, response.Ocs.Meta) - cleanUp(t) - } - } - } -} -func TestDeleteUser(t *testing.T) { - users := []User{ - { - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - }, - { - Enabled: "true", - ID: "thomson", - Email: "thomson@example.com", - Displayname: "J. J. Thomson", - }, - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - for _, user := range users { - err := createUser(user) - if err != nil { - t.Fatal(err) - } - } - - formatpart := getFormatString(format) - res, err := sendRequest( - "DELETE", - fmt.Sprintf("/%s/cloud/users/rutherford%s", ocsVersion, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - assert.Empty(t, response.Ocs.Data) - - // Check deleted user doesn't exist and the other user does - res, err = sendRequest( - "GET", - userProvisioningEndPoint, - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var usersResponse GetUsersResponse - if err := json.Unmarshal(res.Body.Bytes(), &usersResponse); err != nil { - t.Fatal(err) - } - - assert.True(t, usersResponse.Ocs.Meta.Success(ocsV1), unsuccessfulResponseText) - assert.Contains(t, usersResponse.Ocs.Data.Users, "thomson") - assert.NotContains(t, usersResponse.Ocs.Data.Users, "rutherford") - - cleanUp(t) - } - } -} - -func TestDeleteUserInvalidId(t *testing.T) { - - invalidUsers := []string{ - "1", - "invalid", - "3434234233", - "1am41validUs3r", - "_-@@--$$__", - } - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - for _, user := range invalidUsers { - t.Run(fmt.Sprintf("%s (ocs=%s, format=%s)", user, ocsVersion, format), func(t *testing.T) { - formatpart := getFormatString(format) - res, err := sendRequest( - "DELETE", - fmt.Sprintf("/%s/cloud/users/%s%s", ocsVersion, user, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - assert.NoError(t, err) - - response := assertEmptyResponse(t, format, res) - - assertStatusCode(t, 404, res, ocsVersion) - assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was not expected to be successful but was") - assert.Empty(t, response.Ocs.Data) - - assertResponseMeta(t, Meta{ - Status: "error", - StatusCode: 998, - Message: "The requested user could not be found", - }, response.Ocs.Meta) - }) - } - } - } -} - -func TestUpdateUser(t *testing.T) { - user := User{ - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - } - - testData := []struct { - UpdateKey string - UpdateValue string - Error *Meta - }{ - { - "displayname", - "James Chadwick", - nil, - }, - { - "display", - "Neils Bohr", - nil, - }, - { - "email", - "ford@user.org", - nil, - }, - { - "email", - "not_a_valid_email", - &Meta{ - Status: "error", - StatusCode: 400, - Message: "mail 'not_a_valid_email' must be a valid email", - }, - }, - { - "password", - "strongpass1234", - nil, - }, - { - "email", - "", - nil, - }, - { - "password", - "", - nil, - }, - // Invalid Keys - { - "invalid_key", - "validvalue", - &Meta{ - Status: "error", - StatusCode: 103, - Message: "unknown key 'invalid_key'", - }, - }, - { - "12345", - "validvalue", - &Meta{ - Status: "error", - StatusCode: 103, - Message: "unknown key '12345'", - }, - }, - { - "", - "validvalue", - &Meta{ - Status: "error", - StatusCode: 103, - Message: "unknown key ''", - }, - }, - { - "", - "", - &Meta{ - Status: "error", - StatusCode: 103, - Message: "unknown key ''", - }, - }, - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, data := range testData { - err := createUser(user) - if err != nil { - t.Fatalf("Failed while creating user: %v", err) - } - - params := url.Values{} - - params.Add("key", data.UpdateKey) - params.Add("value", data.UpdateValue) - - res, err := sendRequest( - "PUT", - fmt.Sprintf("/%s/cloud/users/rutherford%s", ocsVersion, formatpart), - params.Encode(), - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - updatedUser := user - switch data.UpdateKey { - case "email": - updatedUser.Email = data.UpdateValue - case "displayname": - updatedUser.Displayname = data.UpdateValue - case "display": - updatedUser.Displayname = data.UpdateValue - } - - if err != nil { - t.Fatal(err) - } - - var response struct { - Ocs struct { - Meta Meta `json:"meta" xml:"meta"` - } `json:"ocs" xml:"ocs"` - } - - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - if data.Error != nil { - assertResponseMeta(t, *data.Error, response.Ocs.Meta) - assertStatusCode(t, 400, res, ocsVersion) - } else { - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - assertStatusCode(t, 200, res, ocsVersion) - } - - // Check deleted user doesn't exist and the other user does - res, err = sendRequest( - "GET", - "/v1.php/cloud/users/rutherford?format=json", - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var usersResponse SingleUserResponse - if err := json.Unmarshal(res.Body.Bytes(), &usersResponse); err != nil { - t.Fatal(err) - } - - assert.True(t, usersResponse.Ocs.Meta.Success(ocsV1), unsuccessfulResponseText) - if data.Error == nil { - assertUsersSame(t, updatedUser, usersResponse.Ocs.Data, true) - } else { - assertUsersSame(t, user, usersResponse.Ocs.Data, true) - } - cleanUp(t) - } - } - } -} - -// This is a bug verification test for endpoint '/cloud/user' -// Link to the fixed issue: https://github.com/owncloud/ocis/v2-ocs/issues/52 -func TestGetSingleUser(t *testing.T) { - user := User{ - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - Password: "password", - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - err := createUser(user) - if err != nil { - t.Fatal(err) - } - - a, err := findAccount(t, user.ID) - if err != nil { - t.Fatal(err) - } - - formatpart := getFormatString(format) - res, err := sendRequest( - "GET", - fmt.Sprintf("/%v/cloud/user%v", ocsVersion, formatpart), - "", - &User{ID: a.Id}, - []string{ssvc.BundleUUIDRoleUser}, - ) - - if err != nil { - t.Fatal(err) - } - - var userResponse SingleUserResponse - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &userResponse); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &userResponse.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, userResponse.Ocs.Meta.Success(ocsVersion), "The response was expected to pass but it failed") - assertUserSame(t, user, userResponse.Ocs.Data) - - cleanUp(t) - } - } -} - -// This is a bug demonstration test for endpoint '/cloud/user' -// Link to the issue: https://github.com/owncloud/ocis/v2/issues/53 -func TestGetUserSigningKey(t *testing.T) { - user := User{ - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - Password: "password", - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - err := createUser(user) - if err != nil { - t.Fatal(err) - } - - formatpart := getFormatString(format) - res, err := sendRequest( - "GET", - fmt.Sprintf("/%v/cloud/user/signing-key%v", ocsVersion, formatpart), - "", - &User{ID: user.ID}, - []string{ssvc.BundleUUIDRoleUser}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - - assertStatusCode(t, 500, res, ocsVersion) - assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be a failure but was not") - assertResponseMeta(t, Meta{ - Status: "error", - StatusCode: 996, - Message: "error reading from store", // because the store service is not started - }, response.Ocs.Meta) - assert.Empty(t, response.Ocs.Data) - cleanUp(t) - } - } -} - -func AddUserToGroup(userid, groupid string) error { - res, err := sendRequest( - "POST", - fmt.Sprintf("/v2.php/cloud/users/%s/groups", userid), - fmt.Sprintf("groupid=%v", groupid), - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - if err != nil { - return err - } - if res.Code != 200 { - return fmt.Errorf("Failed while adding the user to group") - } - return nil -} - -func TestListUsersGroupNewUsers(t *testing.T) { - users := []User{ - { - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - }, - { - Enabled: "true", - ID: "thomson", - Email: "thomson@example.com", - Displayname: "J. J. Thomson", - }, - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, user := range users { - err := createUser(user) - if err != nil { - t.Fatal(err) - } - - res, err := sendRequest( - "GET", - fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user.ID, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var response GetUsersGroupsResponse - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - // TODO why should new users be in the users group? - assert.Equal(t, []string{groupUsers}, response.Ocs.Data.Groups) - - cleanUp(t) - } - } - } -} - -func TestListUsersGroupDefaultUsers(t *testing.T) { - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, user := range defaultUsers { - res, err := sendRequest( - "GET", - fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var response GetUsersGroupsResponse - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - - assert.Equal(t, defaultMemberOf[user], response.Ocs.Data.Groups) - } - } - } - cleanUp(t) -} - -func TestGetGroupForUserInvalidUserId(t *testing.T) { - - invalidUsers := []string{ - "1", - "invalid", - "3434234233", - "1am41validUs3r", - "_-@@--$$__", - } - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, user := range invalidUsers { - t.Run(fmt.Sprintf("%s (ocs=%s, format=%s)", user, ocsVersion, format), func(t *testing.T) { - res, err := sendRequest( - "GET", - fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - - assertStatusCode(t, 404, res, ocsVersion) - assert.False(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - assertResponseMeta(t, Meta{ - Status: "error", - StatusCode: 998, - Message: "The requested user could not be found", - }, response.Ocs.Meta) - - assert.Empty(t, response.Ocs.Data) - }) - } - } - } -} - -func TestAddUsersToGroupsNewUsers(t *testing.T) { - users := []User{ - { - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - }, - { - Enabled: "true", - ID: "thomson", - Email: "thomson@example.com", - Displayname: "J. J. Thomson", - }, - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, user := range users { - t.Run(fmt.Sprintf("%s (ocs=%s, format=%s)", user.ID, ocsVersion, format), func(t *testing.T) { - err := createUser(user) - if err != nil { - t.Fatal(err) - } - - // group id for Physics lover - groupid := groupPhysicsLovers - - res, err := sendRequest( - "POST", - fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user.ID, formatpart), - "groupid="+groupid, - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - assert.Empty(t, response.Ocs.Data) - - // Check the user is in the group - res, err = sendRequest( - "GET", - fmt.Sprintf("/%s/cloud/users/%s/groups?format=json", ocsVersion, user.ID), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - if err != nil { - t.Fatal(err) - } - var grpResponse GetUsersGroupsResponse - if err := json.Unmarshal(res.Body.Bytes(), &grpResponse); err != nil { - t.Fatal(err) - } - assert.Contains(t, grpResponse.Ocs.Data.Groups, groupid) - - cleanUp(t) - }) - } - } - } -} - -func TestAddUsersToGroupInvalidGroup(t *testing.T) { - user := User{ - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - } - err := createUser(user) - if err != nil { - t.Fatal(err) - } - - invalidGroups := []string{ - "1", - "invalid", - "3434234233", - "1am41validUs3r", - "_-@@--$$__", - "c7fbe8c4-139b-4376-b307-cf0a8c2d0d9c", - } - - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, groupid := range invalidGroups { - res, err := sendRequest( - "POST", - fmt.Sprintf("/%s/cloud/users/rutherford/groups%s", ocsVersion, formatpart), - "groupid="+groupid, - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - - assertStatusCode(t, 404, res, ocsVersion) - assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to be fail but was successful") - assertResponseMeta(t, Meta{ - "error", - 998, - "The requested group could not be found", - }, response.Ocs.Meta) - assert.Empty(t, response.Ocs.Data) - } - } - } - cleanUp(t) -} - -// Issue: https://github.com/owncloud/ocis/v2/issues/57 - cannot remove user from group -func TestRemoveUserFromGroup(t *testing.T) { - user := User{ - Enabled: "true", - ID: "rutherford", - Email: "rutherford@example.com", - Displayname: "Ernest RutherFord", - } - - groups := []string{ - groupRadiumLovers, - groupPoloniumLovers, - groupPhysicsLovers, - } - - var err error - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - - err = createUser(user) - if err != nil { - t.Fatalf("Failed while creating new user: %v", err) - } - for _, group := range groups { - err := AddUserToGroup(user.ID, group) - if err != nil { - t.Fatalf("Failed while creating new user: %v", err) - } - } - - // Remove user from one group - res, err := sendRequest( - "DELETE", - fmt.Sprintf("/%s/cloud/users/%s/groups%s", ocsVersion, user.ID, formatpart), - "groupid="+groups[0], - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - assert.Empty(t, response.Ocs.Data) - - // Check the users are correctly added to group - res, err = sendRequest( - "GET", - fmt.Sprintf("/%s/cloud/users/%s/groups?format=json", ocsVersion, user.ID), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - if err != nil { - t.Fatal(err) - } - var grpResponse GetUsersGroupsResponse - if err := json.Unmarshal(res.Body.Bytes(), &grpResponse); err != nil { - t.Fatal(err) - } - - assert.NotContains(t, grpResponse.Ocs.Data.Groups, groups[0]) - assert.Contains(t, grpResponse.Ocs.Data.Groups, groups[1]) - assert.Contains(t, grpResponse.Ocs.Data.Groups, groups[2]) - cleanUp(t) - } - } -} - -// Issue: https://github.com/owncloud/ocis/v2-ocs/issues/59 - cloud/capabilities endpoint not implemented -func TestCapabilities(t *testing.T) { - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - res, err := sendRequest( - "GET", - fmt.Sprintf("/%s/cloud/capabilities%s", ocsVersion, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - - assertStatusCode(t, 404, res, ocsVersion) - assertResponseMeta(t, Meta{ - "error", - 998, - "not found", - }, response.Ocs.Meta) - assert.Empty(t, response.Ocs.Data) - } - } -} - -func TestGetConfig(t *testing.T) { - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - res, err := sendRequest( - "GET", - fmt.Sprintf("/%s/config%s", ocsVersion, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var response GetConfigResponse - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - assert.Equal(t, OcsConfig{ - "1.7", "ocis", "", "", "true", - }, response.Ocs.Data) - } - } -} -func TestGetGroupsDefaultGroups(t *testing.T) { - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - - res, err := sendRequest( - "GET", - fmt.Sprintf("/%s/cloud/groups%s", ocsVersion, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var response GetGroupsResponse - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - assert.Subset(t, defaultGroups, response.Ocs.Data.Groups) - } - } -} - -func TestCreateGroup(t *testing.T) { - testData := []struct { - group Group - err *Meta - }{ - // A simple group - { - Group{ - ID: "grp1", - GIDNumber: 32222, - Displayname: "Group Name", - }, - nil, - }, - } - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - for _, data := range testData { - formatpart := getFormatString(format) - res, err := sendRequest( - "POST", - fmt.Sprintf("/%v/cloud/groups%v", ocsVersion, formatpart), - data.group.getGroupRequestString(), - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - - if data.err == nil { - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - } else { - assertResponseMeta(t, *data.err, response.Ocs.Meta) - } - - // Check the group exists of not - res, err = sendRequest( - "GET", - "/v2.php/cloud/groups?format=json", - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - if err != nil { - t.Fatal(err) - } - var groupResponse GetGroupsResponse - if err := json.Unmarshal(res.Body.Bytes(), &groupResponse); err != nil { - t.Fatal(err) - } - if data.err == nil { - assert.Contains(t, groupResponse.Ocs.Data.Groups, data.group.ID) - } else { - assert.NotContains(t, groupResponse.Ocs.Data.Groups, data.group.ID) - } - cleanUp(t) - } - } - } -} - -func TestDeleteGroup(t *testing.T) { - testData := []Group{ - { - ID: "grp1", - GIDNumber: 32222, - Displayname: "Group Name", - }, - } - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, data := range testData { - err := createGroup(data) - if err != nil { - t.Fatal(err) - } - res, err := sendRequest( - "DELETE", - fmt.Sprintf("/%v/cloud/groups/%v%v", ocsVersion, data.ID, formatpart), - "groupid="+data.ID, - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText) - - // Check the group does not exists - res, err = sendRequest( - "GET", - "/v2.php/cloud/groups?format=json", - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - if err != nil { - t.Fatal(err) - } - var groupResponse GetGroupsResponse - if err := json.Unmarshal(res.Body.Bytes(), &groupResponse); err != nil { - t.Fatal(err) - } - - assert.NotContains(t, groupResponse.Ocs.Data.Groups, data.ID) - cleanUp(t) - } - } - } -} - -func TestDeleteGroupInvalidGroups(t *testing.T) { - testData := []string{ - "1", - "invalid", - "3434234233", - "1am41validUs3r", - "_-@@--$$__", - } - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, data := range testData { - res, err := sendRequest( - "DELETE", - fmt.Sprintf("/%v/cloud/groups/%v%v", ocsVersion, data, formatpart), - "groupid="+data, - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - - assertStatusCode(t, 404, res, ocsVersion) - assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to fail but was successful") - assertResponseMeta(t, Meta{ - "error", - 998, - "The requested group could not be found", - }, response.Ocs.Meta) - cleanUp(t) - } - } - } -} - -func TestGetGroupMembersDefaultGroups(t *testing.T) { - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - for group, members := range defaultMembers { - formatpart := getFormatString(format) - res, err := sendRequest( - "GET", - fmt.Sprintf("/%v/cloud/groups/%v%v", ocsVersion, group, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - var response GetGroupMembersResponse - - if format == "json" { - if err := json.Unmarshal(res.Body.Bytes(), &response); err != nil { - t.Fatal(err) - } - } else { - if err := xml.Unmarshal(res.Body.Bytes(), &response.Ocs); err != nil { - t.Fatal(err) - } - } - - assertStatusCode(t, 200, res, ocsVersion) - assert.True(t, response.Ocs.Meta.Success(ocsVersion), unsuccessfulResponseText+" for group "+group) - assert.Equal(t, members, response.Ocs.Data.Users) - - cleanUp(t) - } - } - } -} - -func TestListMembersInvalidGroups(t *testing.T) { - testData := []string{ - "1", - "invalid", - "3434234233", - "1am41validUs3r", - "_-@@--$$__", - } - for _, ocsVersion := range ocsVersions { - for _, format := range formats { - formatpart := getFormatString(format) - for _, group := range testData { - res, err := sendRequest( - "GET", - fmt.Sprintf("/%v/cloud/groups/%v%v", ocsVersion, group, formatpart), - "", - &User{ID: userIDAdmin}, - []string{ssvc.BundleUUIDRoleAdmin}, - ) - - if err != nil { - t.Fatal(err) - } - - response := assertEmptyResponse(t, format, res) - - assertStatusCode(t, 404, res, ocsVersion) - assert.False(t, response.Ocs.Meta.Success(ocsVersion), "The response was expected to fail but was successful") - assertResponseMeta(t, Meta{ - "error", - 998, - "The requested group could not be found", - }, response.Ocs.Meta) - cleanUp(t) - } - } - } -} diff --git a/extensions/ocs/pkg/service/v0/service.go b/extensions/ocs/pkg/service/v0/service.go index bfc6bb5b3d6..4f552b21aff 100644 --- a/extensions/ocs/pkg/service/v0/service.go +++ b/extensions/ocs/pkg/service/v0/service.go @@ -66,15 +66,6 @@ func NewService(opts ...Option) Service { ocsm.Logger(options.Logger), ) - requireAdmin := ocsm.RequireAdmin( - ocsm.RoleManager(roleManager), - ocsm.Logger(options.Logger), - ) - - requireSelfOrAdmin := ocsm.RequireSelfOrAdmin( - ocsm.RoleManager(roleManager), - ocsm.Logger(options.Logger), - ) m.Route(options.Config.HTTP.Root, func(r chi.Router) { r.NotFound(svc.NotFound) r.Use(middleware.StripSlashes) @@ -91,43 +82,8 @@ func NewService(opts ...Option) Service { r.Route("/capabilities", func(r chi.Router) {}) // TODO /apps r.Route("/user", func(r chi.Router) { - r.With(requireSelfOrAdmin).Get("/", svc.GetSelf) r.Get("/signing-key", svc.GetSigningKey) }) - - // for /users endpoints see https://github.com/owncloud/core/blob/master/apps/provisioning_api/appinfo/routes.php#L44-L56 - r.Route("/users", func(r chi.Router) { - r.With(requireAdmin).Get("/", svc.ListUsers) - r.With(requireAdmin).Post("/", svc.AddUser) - r.Route("/{userid}", func(r chi.Router) { - r.With(requireUser).Get("/", svc.GetUser) - r.With(requireSelfOrAdmin).Put("/", svc.EditUser) - r.With(requireAdmin).Delete("/", svc.DeleteUser) - r.With(requireAdmin).Put("/enable", svc.EnableUser) - r.With(requireAdmin).Put("/disable", svc.DisableUser) - }) - - r.Route("/{userid}/groups", func(r chi.Router) { - r.With(requireSelfOrAdmin).Get("/", svc.ListUserGroups) - r.With(requireAdmin).Post("/", svc.AddToGroup) - r.With(requireAdmin).Delete("/", svc.RemoveFromGroup) - }) - - r.Route("/{userid}/subadmins", func(r chi.Router) { - r.With(requireAdmin).Post("/", svc.NotImplementedStub) - r.With(requireSelfOrAdmin).Get("/", svc.NotImplementedStub) - r.With(requireAdmin).Delete("/", svc.NotImplementedStub) - }) - }) - - // for /groups endpoints see https://github.com/owncloud/core/blob/master/apps/provisioning_api/appinfo/routes.php#L65-L69 - r.Route("/groups", func(r chi.Router) { - r.With(requireAdmin).Get("/", svc.ListGroups) - r.With(requireAdmin).Post("/", svc.AddGroup) - r.With(requireSelfOrAdmin).Get("/{groupid}", svc.GetGroupMembers) - r.With(requireAdmin).Delete("/{groupid}", svc.DeleteGroup) - r.With(requireAdmin).Get("/{groupid}/subadmins", svc.NotImplementedStub) - }) }) r.Route("/config", func(r chi.Router) { r.With(requireUser).Get("/", svc.GetConfig) diff --git a/extensions/proxy/pkg/config/defaults/defaultconfig.go b/extensions/proxy/pkg/config/defaults/defaultconfig.go index ae52d712134..87e803d7068 100644 --- a/extensions/proxy/pkg/config/defaults/defaultconfig.go +++ b/extensions/proxy/pkg/config/defaults/defaultconfig.go @@ -85,7 +85,7 @@ func DefaultPolicies() []config.Policy { }, { Type: config.RegexRoute, - Endpoint: "/ocs/v[12].php/cloud/(users?|groups)", // we have `user`, `users` and `groups` in ocis-ocs + Endpoint: "/ocs/v[12].php/cloud/user/signing-key", // only `user/signing-key` is left in ocis-ocs Backend: "http://localhost:9110", }, {